home *** CD-ROM | disk | FTP | other *** search
/ Chip 2007 January, February, March & April / Chip-Cover-CD-2007-02.iso / Pakiet internetowy / Rozne / HTTrack 3.40-2 / httrack-3.40-2.exe / {app} / src / htscoremain.c < prev    next >
C/C++ Source or Header  |  2006-01-21  |  99KB  |  2,533 lines

  1. /* ------------------------------------------------------------ */
  2. /*
  3. HTTrack Website Copier, Offline Browser for Windows and Unix
  4. Copyright (C) Xavier Roche and other contributors
  5.  
  6. This program is free software; you can redistribute it and/or
  7. modify it under the terms of the GNU General Public License
  8. as published by the Free Software Foundation; either version 2
  9. of the License, or any later version.
  10.  
  11. This program is distributed in the hope that it will be useful,
  12. but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  14. GNU General Public License for more details.
  15.  
  16. You should have received a copy of the GNU General Public License
  17. along with this program; if not, write to the Free Software
  18. Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA  02111-1307, USA.
  19.  
  20.  
  21. Important notes:
  22.  
  23. - We hereby ask people using this source NOT to use it in purpose of grabbing
  24. emails addresses, or collecting any other private information on persons.
  25. This would disgrace our work, and spoil the many hours we spent on it.
  26.  
  27.  
  28. Please visit our Website: http://www.httrack.com
  29. */
  30.  
  31.  
  32. /* ------------------------------------------------------------ */
  33. /* File: httrack.c subroutines:                                 */
  34. /*       main routine (first called)                            */
  35. /* Author: Xavier Roche                                         */
  36. /* ------------------------------------------------------------ */
  37.  
  38. /* Internal engine bytecode */
  39. #define HTS_INTERNAL_BYTECODE
  40.  
  41. #include "htscoremain.h"
  42.  
  43. #include "htsglobal.h"
  44. #include "htscore.h"
  45. #include "htsdefines.h"
  46. #include "htsalias.h"
  47. #include "htswrap.h"
  48. #include "htsmodules.h"
  49. #include "htszlib.h"
  50.  
  51. #include <ctype.h>
  52. #if USE_BEGINTHREAD
  53. #if HTS_WIN
  54. #include <process.h>
  55. #endif
  56. #endif
  57. #if HTS_WIN
  58. #else
  59. #ifndef HTS_DO_NOT_USE_UID
  60. /* setuid */
  61. #include <pwd.h>
  62. #ifdef HAVE_UNISTD_H
  63. #include <unistd.h>
  64. #endif
  65. #endif
  66. #endif
  67.  
  68. extern int exit_xh;          // sortir prΘmaturΘment
  69.  
  70. /* Resolver */
  71. extern int IPV6_resolver;
  72.  
  73.  
  74. // Add a command in the argc/argv
  75. #define cmdl_add(token,argc,argv,buff,ptr) \
  76.   argv[argc]=(buff+ptr); \
  77.   strcpybuff(argv[argc],token); \
  78.   ptr += (strlen(argv[argc])+2); \
  79.   argc++
  80.  
  81. // Insert a command in the argc/argv
  82. #define cmdl_ins(token,argc,argv,buff,ptr) \
  83.   { \
  84.   int i; \
  85.   for(i=argc;i>0;i--)\
  86.   argv[i]=argv[i-1];\
  87.   } \
  88.   argv[0]=(buff+ptr); \
  89.   strcpybuff(argv[0],token); \
  90.   ptr += (strlen(argv[0])+2); \
  91.   argc++
  92.  
  93. #define htsmain_free() do { if (url != NULL) { free(url); } } while(0)
  94.  
  95. #define ensureUrlCapacity(url, urlsize, size) do { \
  96.   if (urlsize < size || url == NULL) { \
  97.     urlsize = size; \
  98.     if (url == NULL) { \
  99.       url = (char*) malloct(urlsize); \
  100.       if (url != NULL) url[0]='\0'; \
  101.     } else { \
  102.       url = (char*) realloct(url, urlsize); \
  103.     } \
  104.     if (url == NULL) { \
  105.       HTS_PANIC_PRINTF("* memory exhausted"); \
  106.       htsmain_free(); \
  107.       return -1; \
  108.     } \
  109.   } \
  110. } while(0)
  111.  
  112. void set_wrappers(void) {
  113. #if HTS_ANALYSTE
  114.   // custom wrappers
  115.   hts_htmlcheck_init         = (t_hts_htmlcheck_init)           htswrap_read("init");
  116.   hts_htmlcheck_uninit       = (t_hts_htmlcheck_uninit)         htswrap_read("free");
  117.   hts_htmlcheck_start        = (t_hts_htmlcheck_start)          htswrap_read("start");
  118.   hts_htmlcheck_end          = (t_hts_htmlcheck_end)            htswrap_read("end");
  119.   hts_htmlcheck_chopt        = (t_hts_htmlcheck_chopt)          htswrap_read("change-options");
  120.   hts_htmlcheck_preprocess   = (t_hts_htmlcheck_process)        htswrap_read("preprocess-html");
  121.   hts_htmlcheck_postprocess  = (t_hts_htmlcheck_process)        htswrap_read("postprocess-html");
  122.   hts_htmlcheck              = (t_hts_htmlcheck)                htswrap_read("check-html");
  123.   hts_htmlcheck_query        = (t_hts_htmlcheck_query)          htswrap_read("query");
  124.   hts_htmlcheck_query2       = (t_hts_htmlcheck_query2)         htswrap_read("query2");
  125.   hts_htmlcheck_query3       = (t_hts_htmlcheck_query3)         htswrap_read("query3");
  126.   hts_htmlcheck_loop         = (t_hts_htmlcheck_loop)           htswrap_read("loop");
  127.   hts_htmlcheck_check        = (t_hts_htmlcheck_check)          htswrap_read("check-link");
  128.   hts_htmlcheck_check_mime   = (t_hts_htmlcheck_check_mime)     htswrap_read("check-mime");
  129.   hts_htmlcheck_pause        = (t_hts_htmlcheck_pause)          htswrap_read("pause");
  130.   hts_htmlcheck_filesave     = (t_hts_htmlcheck_filesave)       htswrap_read("save-file");
  131.   hts_htmlcheck_filesave2    = (t_hts_htmlcheck_filesave2)      htswrap_read("save-file2");
  132.   hts_htmlcheck_linkdetected = (t_hts_htmlcheck_linkdetected)   htswrap_read("link-detected");
  133.   hts_htmlcheck_linkdetected2 = (t_hts_htmlcheck_linkdetected2) htswrap_read("link-detected2");
  134.   hts_htmlcheck_xfrstatus    = (t_hts_htmlcheck_xfrstatus)      htswrap_read("transfer-status");
  135.   hts_htmlcheck_savename     = (t_hts_htmlcheck_savename)       htswrap_read("save-name");
  136.   hts_htmlcheck_sendhead     = (t_hts_htmlcheck_sendhead)       htswrap_read("send-header");
  137.   hts_htmlcheck_receivehead  = (t_hts_htmlcheck_receivehead)    htswrap_read("receive-header");
  138. #endif
  139. }
  140.  
  141. // Main, rΘcupΦre les paramΦtres et appelle le robot
  142. #if HTS_ANALYSTE
  143. HTSEXT_API int hts_main(int argc, char **argv) {
  144. #else
  145. int main(int argc, char **argv) {
  146. #endif
  147.   char** x_argv=NULL;     // Patch pour argv et argc: en cas de rΘcupΘration de ligne de commande
  148.   char* x_argvblk=NULL;   // (reprise ou update)
  149.   int   x_ptr=0;          // offset
  150.   //
  151.   int argv_url=-1;           // ==0 : utiliser cache et doit.log
  152.   char* argv_firsturl=NULL;  // utilisΘ pour nommage par dΘfaut
  153.   char* url = NULL;          // URLS sΘparΘes par un espace
  154.   int   url_sz = 65535;
  155.   //char url[65536];         // URLS sΘparΘes par un espace
  156.   // the parametres
  157.   httrackp BIGSTK httrack;
  158.   int httrack_logmode=3;   // ONE log file
  159.   int recuperer=0;         // rΘcupΘrer un plantage (n'arrive jamais, α supprimer)
  160. #if HTS_WIN
  161. #if HTS_ANALYSTE!=2
  162.   WORD   wVersionRequested; /* requested version WinSock API */ 
  163.   WSADATA BIGSTK wsadata;   /* Windows Sockets API data */
  164. #endif
  165. #else
  166. #ifndef HTS_DO_NOT_USE_UID
  167.   int switch_uid=-1,switch_gid=-1;      /* setuid/setgid */
  168. #endif
  169.   int switch_chroot=0;                  /* chroot ? */
  170. #endif
  171.   //
  172.   ensureUrlCapacity(url, url_sz, 65536);
  173.   //
  174.  
  175. #if HTS_ANALYSTE
  176.   // custom wrappers
  177.   set_wrappers();
  178. #endif
  179.  
  180.   // options par dΘfaut
  181.   memset(&httrack, 0, sizeof(httrackp));
  182.   httrack.wizard=2;   // wizard automatique
  183.   httrack.quiet=0;     // questions
  184.   //  
  185.   httrack.travel=0;   // mΩme adresse
  186.   httrack.depth=9999; // mirror total par dΘfaut
  187.   httrack.extdepth=0; // mais pas α l'extΘrieur
  188.   httrack.seeker=1;   // down 
  189.   httrack.urlmode=2;  // relatif par dΘfaut
  190.   httrack.debug=0;    // pas de dΘbug en plus
  191.   httrack.getmode=3;  // linear scan
  192.   httrack.maxsite=-1; // taille max site (aucune)
  193.   httrack.maxfile_nonhtml=-1; // taille max fichier non html
  194.   httrack.maxfile_html=-1;    // idem pour html
  195.   httrack.maxsoc=4;     // nbre socket max
  196.   httrack.fragment=-1;  // pas de fragmentation
  197.   httrack.nearlink=0;   // ne pas prendre les liens non-html "adjacents"
  198.   httrack.makeindex=1;  // faire un index
  199.   httrack.kindex=0;     // index 'keyword'
  200.   httrack.delete_old=1; // effacer anciens fichiers
  201.   httrack.makestat=0;  // pas de fichier de stats
  202.   httrack.maketrack=0; // ni de tracking
  203.   httrack.timeout=120; // timeout par dΘfaut (2 minutes)
  204.   httrack.cache=1;     // cache prioritaire
  205.   httrack.shell=0;     // pas de shell par defaut
  206.   httrack.proxy.active=0;    // pas de proxy
  207.   strcpybuff(httrack.proxy.bindhost, "");  // bind default host
  208.   httrack.user_agent_send=1; // envoyer un user-agent
  209.   strcpybuff(httrack.user_agent,"Mozilla/4.5 (compatible; HTTrack 3.0x; Windows 98)");
  210.   strcpybuff(httrack.referer, "");
  211.   strcpybuff(httrack.from, "");
  212.   httrack.savename_83=0;     // noms longs par dΘfaut
  213.   httrack.savename_type=0;   // avec structure originale
  214.   httrack.savename_delayed=2;// hard delayed type (default)
  215.   httrack.delayed_cached=1;  // cached delayed type (default)
  216.   httrack.mimehtml=0;        // pas MIME-html
  217.   httrack.parsejava=1;       // parser classes
  218.   httrack.hostcontrol=0;     // PAS de control host pour timeout et traffic jammer
  219.   httrack.retry=2;           // 2 retry par dΘfaut
  220.   httrack.errpage=1;         // copier ou gΘnΘrer une page d'erreur en cas d'erreur (404 etc.)
  221.   httrack.check_type=1;      // vΘrifier type si inconnu (cgi,asp..) SAUF / considΘrΘ comme html
  222.   httrack.all_in_cache=0;    // ne pas tout stocker en cache
  223.   httrack.robots=2;          // traiter les robots.txt
  224.   httrack.external=0;        // liens externes normaux
  225.   httrack.passprivacy=0;     // mots de passe dans les fichiers
  226.   httrack.includequery=1;    // include query-string par dΘfaut
  227.   httrack.mirror_first_page=0;  // pas mode mirror links
  228.   httrack.accept_cookie=1;   // gΘrer les cookies
  229.   httrack.cookie=NULL;
  230.   httrack.http10=0;          // laisser http/1.1
  231.   httrack.nokeepalive = 0;   // pas keep-alive
  232.   httrack.nocompression=0;   // pas de compression
  233.   httrack.tolerant=0;        // ne pas accepter content-length incorrect
  234.   httrack.parseall=1;        // tout parser (tags inconnus, par exemple)
  235.   httrack.parsedebug=0;      // pas de mode dΘbuggage
  236.   httrack.norecatch=0;       // ne pas reprendre les fichiers effacΘs par l'utilisateur
  237.   httrack.verbosedisplay=0;  // pas d'animation texte
  238.   httrack.sizehack=0;        // size hack
  239.   httrack.urlhack=1;         // url hack (normalizer)
  240.   strcpybuff(httrack.footer,HTS_DEFAULT_FOOTER);
  241.   httrack.ftp_proxy=1;       // proxy http pour ftp
  242.   strcpybuff(httrack.filelist,"");
  243.   strcpybuff(httrack.lang_iso,"en, *");
  244.   strcpybuff(httrack.mimedefs,"\n"); // aucun filtre mime (\n IMPORTANT)
  245.   //
  246.   httrack.log=stdout;
  247.   httrack.errlog=stderr;
  248.   httrack.flush=1;           // flush sur les fichiers log
  249.   //httrack.aff_progress=0;
  250.   httrack.keyboard=0;
  251.   //
  252.   strcpybuff(httrack.path_html,"");
  253.   strcpybuff(httrack.path_log,"");
  254.   strcpybuff(httrack.path_bin,"");
  255.   //
  256. #if HTS_SPARE_MEMORY==0
  257.   httrack.maxlink=100000;    // 100,000 liens max par dΘfaut (400Kb)
  258.   httrack.maxfilter=200;     // 200 filtres max par dΘfaut
  259. #else
  260.   httrack.maxlink=10000;     // 10,000 liens max par dΘfaut (40Kb)
  261.   httrack.maxfilter=50;      // 50 filtres max par dΘfaut
  262. #endif
  263.   httrack.maxcache=1048576*32;  // a peu prΦs 32Mo en cache max -- OPTION NON PARAMETRABLE POUR L'INSTANT --
  264.   //httrack.maxcache_anticipate=256;  // maximum de liens α anticiper
  265.   httrack.maxtime=-1;        // temps max en secondes
  266. #if HTS_USEMMS
  267.     httrack.mms_maxtime = 60*3600;        // max time for mms streams (one hour)
  268. #endif
  269.   httrack.maxrate=25000;     // taux maxi
  270.   httrack.maxconn=5.0;       // nombre connexions/s
  271.   httrack.waittime=-1;       // wait until.. hh*3600+mm*60+ss
  272.   //
  273.   httrack.exec=argv[0];
  274.   httrack.is_update=0;      // not an update (yet)
  275.   httrack.dir_topindex=0;   // do not built top index (yet)
  276.   //
  277.   httrack.bypass_limits=0;  // enforce limits by default
  278.   httrack.state.stop=0;     // stopper
  279.   httrack.state.exit_xh=0;  // abort
  280.   //
  281.   _DEBUG_HEAD=0;            // pas de debuggage en tΩtes
  282.  
  283.   
  284. #if HTS_WIN
  285. #if HTS_ANALYSTE!=2
  286.   {
  287.     int stat;
  288.     wVersionRequested = 0x0101;
  289.     stat = WSAStartup( wVersionRequested, &wsadata );
  290.     if (stat != 0) {
  291.       HTS_PANIC_PRINTF("Winsock not found!\n");
  292.       htsmain_free();
  293.       return -1;
  294.     } else if (LOBYTE(wsadata.wVersion) != 1  && HIBYTE(wsadata.wVersion) != 1) {
  295.       HTS_PANIC_PRINTF("WINSOCK.DLL does not support version 1.1\n");
  296.       WSACleanup();
  297.       htsmain_free();
  298.       return -1;
  299.     }
  300.   }
  301. #endif
  302. #endif
  303.  
  304.   /* Init root dir */
  305.   hts_rootdir(argv[0]);
  306.  
  307. #if HTS_WIN
  308. #else
  309.   /* Terminal is a tty, may ask questions and display funny information */
  310.   if (isatty(1)) {
  311.     httrack.quiet=0;
  312.     httrack.verbosedisplay=1;
  313.   }
  314.   /* Not a tty, no stdin input or funny output! */
  315.   else {
  316.     httrack.quiet=1;
  317.     httrack.verbosedisplay=0;
  318.   }
  319. #endif
  320.  
  321.   /* First test: if -#R then only launch ftp */
  322.   if (argc > 2) {
  323.     if (strcmp(argv[1],"-#R")==0) {
  324.       if (argc==6) {
  325.         lien_back r;
  326.         char* path;
  327.         FILE* fp;
  328.         strcpybuff(r.url_adr,argv[2]);
  329.         strcpybuff(r.url_fil,argv[3]);
  330.         strcpybuff(r.url_sav,argv[4]);
  331.         path=argv[5];
  332.         r.status=1000;
  333.         run_launch_ftp(&r);
  334.         fp=fopen(fconv(path),"wb");
  335.         if (fp) {
  336.           fprintf(fp,"%d %s",r.r.statuscode,r.r.msg);
  337.           fclose(fp); fp=NULL;
  338.           rename(fconv(path),fconcat(path,".ok"));
  339.         } else remove(fconv(path));
  340.       } else {
  341.         printf("htsftp error, wrong parameter number (%d)\n",argc);
  342.       }
  343.       exit(0);   // pas _exit()
  344.     }
  345.   }
  346.  
  347.   // ok, non ftp, continuer
  348.  
  349.  
  350.   // Binary program path?
  351. #ifndef HTS_HTTRACKDIR
  352.   {
  353.     char* path=fslash(argv[0]);
  354.     char* a;
  355.     if ((a=strrchr(path,'/'))) {
  356.       httrack.path_bin[0]='\0';
  357.       strncatbuff(httrack.path_bin,argv[0],(int) a - (int) path);
  358.     }
  359.   }
  360. #else
  361.   strcpybuff(httrack.path_bin, HTS_HTTRACKDIR);
  362. #endif
  363.  
  364.   /* libhttrack-plugin DLL preload (libhttrack-plugin.so or libhttrack-plugin.dll) */
  365.   {
  366.     void* userfunction = getFunctionPtr(&httrack, "libhttrack-plugin", "plugin_init");
  367.     if (userfunction != NULL) {
  368.       t_hts_htmlcheck_init initFnc = (t_hts_htmlcheck_init) userfunction;
  369.       initFnc();
  370.       set_wrappers();        /* Re-read wrappers internal static functions */
  371.     }
  372.   }
  373.  
  374.   /* filter CR, LF, TAB.. */
  375.   {
  376.     int na;
  377.     for(na=1;na<argc;na++) {
  378.       char* a;
  379.       while( (a=strchr(argv[na],'\x0d')) ) *a=' ';
  380.       while( (a=strchr(argv[na],'\x0a')) ) *a=' ';
  381.       while( (a=strchr(argv[na],9)) )      *a=' ';
  382.       /* equivalent to "empty parameter" */
  383.       if ((strcmp(argv[na],HTS_NOPARAM)==0) || (strcmp(argv[na],HTS_NOPARAM2)==0))        // (none)
  384.         strcpybuff(argv[na],"\"\"");
  385.       if (strncmp(argv[na],"-&",2)==0)
  386.         argv[na][1]='%';
  387.     }
  388.   }
  389.  
  390.  
  391.  
  392.   /* create x_argvblk buffer for transformed command line */
  393.   {
  394.     int current_size=0;
  395.     int size;
  396.     int na;
  397.     for(na=0;na<argc;na++)
  398.       current_size += (strlen(argv[na]) + 1);
  399.     if ((size=fsize("config"))>0)
  400.       current_size += size;
  401.     x_argvblk=(char*) malloct(current_size+32768);
  402.     if (x_argvblk == NULL) {
  403.       HTS_PANIC_PRINTF("Error, not enough memory");
  404.       htsmain_free();
  405.       return -1;
  406.     }
  407.     x_argvblk[0]='\0';
  408.     x_ptr=0;
  409.  
  410.     /* Create argv */
  411.     x_argv = (char**) malloct(sizeof(char*) * ( argc + 1024 ));
  412.   }
  413.  
  414.   /* Create new argc/argv, replace alias, count URLs, treat -h, -q, -i */
  415.   {
  416.     char BIGSTK _tmp_argv[2][HTS_CDLMAXSIZE];
  417.     char BIGSTK tmp_error[HTS_CDLMAXSIZE];
  418.     char* tmp_argv[2];
  419.     int tmp_argc;
  420.     int x_argc=0;
  421.     int na;
  422.     tmp_argv[0]=_tmp_argv[0];
  423.     tmp_argv[1]=_tmp_argv[1];
  424.     //
  425.     argv_url=0;       /* pour comptage */
  426.     //
  427.     cmdl_add(argv[0],x_argc,x_argv,x_argvblk,x_ptr);
  428.     na=1;             /* commencer aprΦs nom_prg */
  429.     while(na<argc) {
  430.       int result=1;
  431.       tmp_argv[0][0]=tmp_argv[1][0]='\0';
  432.  
  433.       /* VΘrifier argv[] non vide */
  434.       if (strnotempty(argv[na])) {
  435.         
  436.         /* VΘrifier Commande (alias) */
  437.         result=optalias_check(argc,(const char * const *)argv,na,
  438.           &tmp_argc,(char**)tmp_argv,tmp_error);
  439.         if (!result) {
  440.           HTS_PANIC_PRINTF(tmp_error);
  441.           htsmain_free();
  442.           return -1;
  443.         }
  444.         
  445.         /* Copier */
  446.         cmdl_add(tmp_argv[0],x_argc,x_argv,x_argvblk,x_ptr);
  447.         if (tmp_argc > 1) {
  448.           cmdl_add(tmp_argv[1],x_argc,x_argv,x_argvblk,x_ptr);
  449.         }
  450.         
  451.         /* Compter URLs et dΘtecter -i,-q.. */
  452.         if (tmp_argc == 1) {           /* pas -P & co */
  453.           if (!cmdl_opt(tmp_argv[0])) {   /* pas -c0 & co */
  454.             if (argv_url<0) argv_url=0;   // -1==force -> 1=one url already detected, wipe all previous options
  455.             //if (argv_url>=0) {
  456.             argv_url++;
  457.             if (!argv_firsturl)
  458.               argv_firsturl=x_argv[x_argc-1];
  459.             //}
  460.           } else {
  461.             if (strcmp(tmp_argv[0],"-h")==0) {
  462.               help(argv[0],!httrack.quiet);
  463.               htsmain_free();
  464.               return 0;
  465.             } else {
  466.               if (strncmp(tmp_argv[0],"--",2)) {   /* pas */
  467.                 if ((strchr(tmp_argv[0],'q')!=NULL))
  468.                   httrack.quiet=1;    // ne pas poser de questions! (nohup par exemple)
  469.                 if ((strchr(tmp_argv[0],'i')!=NULL)) {  // doit.log!
  470.                   argv_url=-1;        /* forcer */
  471.                   httrack.quiet=1;
  472.                 }
  473.               } else if (strcmp(tmp_argv[0] + 2,"quiet") == 0) {
  474.                 httrack.quiet=1;    // ne pas poser de questions! (nohup par exemple)
  475.               } else if (strcmp(tmp_argv[0] + 2,"continue") == 0) {
  476.                 argv_url=-1;        /* forcer */
  477.                 httrack.quiet=1;
  478.               }
  479.             }
  480.           }
  481.         } else if (tmp_argc == 2) {
  482.           if ((strcmp(tmp_argv[0],"-%L")==0)) {  // liste d'URLs
  483.             if (argv_url<0) argv_url=0;   // -1==force -> 1=one url already detected, wipe all previous options
  484.             //if (argv_url>=0)
  485.             argv_url++;        /* forcer */
  486.           }
  487.         }
  488.       }
  489.  
  490.       na+=result;
  491.     }
  492.     if (argv_url<0)
  493.       argv_url=0;
  494.  
  495.     /* Nouveaux argc et argv */
  496.     argv=x_argv;
  497.     argc=x_argc;
  498.   }
  499.  
  500.   // Option O and includerc
  501.   { 
  502.     int loops=0;
  503.     while (loops<2) {
  504.       char* com;
  505.       int na;
  506.       
  507.       for(na=1;na<argc;na++) {
  508.         
  509.         if (argv[na][0]=='"') {
  510.           char BIGSTK tempo[HTS_CDLMAXSIZE];
  511.           strcpybuff(tempo,argv[na]+1);
  512.           if (tempo[strlen(tempo)-1]!='"') {
  513.             char BIGSTK s[HTS_CDLMAXSIZE];
  514.             sprintf(s,"Missing quote in %s",argv[na]);
  515.             HTS_PANIC_PRINTF(s);
  516.             htsmain_free();
  517.             return -1;
  518.           }
  519.           tempo[strlen(tempo)-1]='\0';
  520.           strcpybuff(argv[na],tempo);
  521.         }
  522.         
  523.         if (cmdl_opt(argv[na])) { // option
  524.           com=argv[na]+1;
  525.           
  526.           while(*com) {
  527.             switch(*com) {
  528.             case 'O':    // output path
  529.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  530.                 HTS_PANIC_PRINTF("Option O needs to be followed by a blank space, and a path (or path,path)");
  531.                 printf("Example: -O /binary/\n");
  532.                 printf("Example: -O /binary/,/log/\n");
  533.                 htsmain_free();
  534.                 return -1;
  535.               } else {
  536.                                 int i, j;
  537.                                 int inQuote;
  538.                                 char* path;
  539.                                 int noDbl = 0;
  540.                                 if (com[1] == '1') {            /* only 1 arg */
  541.                                     com++;
  542.                                     noDbl = 1;
  543.                                 }
  544.                 na++;
  545.                                 httrack.path_html[0] = '\0';
  546.                 httrack.path_log[0] = '\0';
  547.                                 for(i = 0, j = 0, inQuote = 0, path = httrack.path_html ; argv[na][i] != 0 ; i++) {
  548.                                     if (argv[na][i] == '"') {
  549.                                         if (inQuote)
  550.                                             inQuote = 0;
  551.                                         else
  552.                                             inQuote = 1;
  553.                                     } else if (!inQuote && !noDbl && argv[na][i] == ',') {
  554.                                         path[j++] = '\0';
  555.                                         j = 0;
  556.                                         path = httrack.path_log;
  557.                                     } else {
  558.                                         path[j++] = argv[na][i];
  559.                                     }
  560.                                 }
  561.                                 path[j++] = '\0';
  562.                                 if (httrack.path_log[0] == '\0') {
  563.                                     strcpybuff(httrack.path_log, httrack.path_html);
  564.                                 }
  565.  
  566.                 check_path(httrack.path_log,argv_firsturl);
  567.                 if (check_path(httrack.path_html,argv_firsturl)) {
  568.                   httrack.dir_topindex=1;     // rebuilt top index
  569.                 }
  570.                 
  571.                 //printf("-->%s\n%s\n",httrack.path_html,httrack.path_log);                
  572.               }
  573.               break;
  574.             }  // switch
  575.             com++;    
  576.           }  // while
  577.           
  578.         }  // arg
  579.         
  580.       }  // for
  581.      
  582.          /* if doit.log exists, or if new URL(s) defined, 
  583.       then DO NOT load standard config files */
  584.       /* (config files are added in doit.log) */
  585. #if DEBUG_STEPS
  586.       printf("Loading httrackrc/doit.log\n");
  587. #endif
  588.       /* recreate a doit.log (no old doit.log or new URLs (and parameters)) */
  589.       if ((strnotempty(httrack.path_log)) || (strnotempty(httrack.path_html)))
  590.         loops++;      // do not loop once again and do not include rc file (O option exists)
  591.       else {
  592.         if ( (!fexist(fconcat(httrack.path_log,"hts-cache/doit.log"))) || (argv_url>0) ) {
  593.           if (!optinclude_file(fconcat(httrack.path_log,HTS_HTTRACKRC),&argc,argv,x_argvblk,&x_ptr))
  594.             if (!optinclude_file(HTS_HTTRACKRC,&argc,argv,x_argvblk,&x_ptr)) {
  595.               if (!optinclude_file(fconcat(hts_gethome(),"/"HTS_HTTRACKRC),&argc,argv,x_argvblk,&x_ptr)) {
  596. #ifdef HTS_HTTRACKCNF
  597.                 optinclude_file(HTS_HTTRACKCNF,&argc,argv,x_argvblk,&x_ptr);
  598. #endif
  599.               }
  600.             }
  601.         } else
  602.           loops++;      // do not loop once again
  603.       }
  604.  
  605.       loops++;
  606.    } // while
  607.  
  608.   }  // traiter -O
  609.  
  610.   /* load doit.log and insert in current command line */
  611.   if ( fexist(fconcat(httrack.path_log,"hts-cache/doit.log")) && (argv_url<=0) ) {
  612.     FILE* fp=fopen(fconcat(httrack.path_log,"hts-cache/doit.log"),"rb");
  613.     if (fp) {
  614.       int insert_after=1;     /* insΘrer aprΦs nom au dΘbut */
  615.       //
  616.       char BIGSTK buff[8192];
  617.       char *p,*lastp;
  618.       linput(fp,buff,8000);
  619.       fclose(fp); fp=NULL;
  620.       p=buff;
  621.       do {
  622.         int insert_after_argc;
  623.         // read next
  624.         lastp=p;
  625.         if (p) {
  626.           p=next_token(p,1);
  627.           if (p) {
  628.             *p=0;    // null
  629.             p++;
  630.           }
  631.         }
  632.  
  633.         /* Insert parameters BUT so that they can be in the same order */
  634.         if (lastp) {
  635.           if (strnotempty(lastp)) {
  636.             insert_after_argc=argc-insert_after;
  637.             cmdl_ins(lastp,insert_after_argc,(argv+insert_after),x_argvblk,x_ptr);
  638.             argc=insert_after_argc+insert_after;
  639.             insert_after++;
  640.           }
  641.         }
  642.       } while(lastp!=NULL);
  643.       //fclose(fp);
  644.     }
  645.   }
  646.  
  647.  
  648.   // Existence d'un cache - pas de new mais un old.. renommer
  649. #if DEBUG_STEPS
  650.   printf("Checking cache\n");
  651. #endif
  652.   if (!fexist(fconcat(httrack.path_log,"hts-cache/new.zip"))) {
  653.     if ( fexist(fconcat(httrack.path_log,"hts-cache/old.zip")) ) {
  654.       rename(fconcat(httrack.path_log,"hts-cache/old.zip"),fconcat(httrack.path_log,"hts-cache/new.zip"));
  655.     }
  656.   } else if ( (!fexist(fconcat(httrack.path_log,"hts-cache/new.dat"))) || (!fexist(fconcat(httrack.path_log,"hts-cache/new.ndx"))) ) {
  657.     if ( (fexist(fconcat(httrack.path_log,"hts-cache/old.dat"))) && (fexist(fconcat(httrack.path_log,"hts-cache/old.ndx"))) ) {
  658.       remove(fconcat(httrack.path_log,"hts-cache/new.dat"));
  659.       remove(fconcat(httrack.path_log,"hts-cache/new.ndx"));
  660.       //remove(fconcat(httrack.path_log,"hts-cache/new.lst"));
  661.       rename(fconcat(httrack.path_log,"hts-cache/old.dat"),fconcat(httrack.path_log,"hts-cache/new.dat"));
  662.       rename(fconcat(httrack.path_log,"hts-cache/old.ndx"),fconcat(httrack.path_log,"hts-cache/new.ndx"));
  663.       //rename(fconcat(httrack.path_log,"hts-cache/old.lst"),fconcat(httrack.path_log,"hts-cache/new.lst"));
  664.     }
  665.   }
  666.  
  667.   /* Interrupted mirror detected */
  668.   if (!httrack.quiet) {
  669.     if (fexist(fconcat(httrack.path_log,"hts-in_progress.lock"))) {
  670.       /* Old cache */
  671.       if ( (fexist(fconcat(httrack.path_log,"hts-cache/old.dat"))) && (fexist(fconcat(httrack.path_log,"hts-cache/old.ndx"))) ) {
  672.         if (httrack.log != NULL) {
  673.           fprintf(httrack.log,"Warning!\n");
  674.           fprintf(httrack.log,"An aborted mirror has been detected!\nThe current temporary cache is required for any update operation and only contains data downloaded during the last aborted session.\nThe former cache might contain more complete information; if you do not want to lose that information, you have to restore it and delete the current cache.\nThis can easily be done here by erasing the hts-cache/new.* files\n");
  675.           fprintf(httrack.log,"Please restart HTTrack with --continue (-iC1) option to override this message!\n");
  676.         }
  677.         exit(0);
  678.       }
  679.     }
  680.   }
  681.     
  682.   // remplacer "macros" comme --spider
  683.   // permet de lancer httrack sans a avoir α se rappeler de syntaxes comme p0C0I0Qc32 ..
  684. #if DEBUG_STEPS
  685.   printf("Checking last macros\n");
  686. #endif
  687.   {
  688.     int i;
  689.     for(i=0;i<argc;i++) {
  690. #if DEBUG_STEPS
  691.       printf("Checking #%d:\n",argv[i]);
  692.       printf("%s\n",argv[i]);
  693. #endif
  694.       if (argv[i][0]=='-') {
  695.         if (argv[i][1]=='-') {  // --xxx
  696.           if ((strfield2(argv[i]+2,"clean")) || (strfield2(argv[i]+2,"tide"))) {  // nettoyer
  697.             strcpybuff(argv[i]+1,"");
  698.             if (fexist(fconcat(httrack.path_log,"hts-log.txt")))
  699.               remove(fconcat(httrack.path_log,"hts-log.txt"));
  700.             if (fexist(fconcat(httrack.path_log,"hts-err.txt")))
  701.               remove(fconcat(httrack.path_log,"hts-err.txt"));
  702.             if (fexist(fconcat(httrack.path_html,"index.html")))
  703.               remove(fconcat(httrack.path_html,"index.html"));
  704.             /* */
  705.             if (fexist(fconcat(httrack.path_log,"hts-cache/new.zip")))
  706.               remove(fconcat(httrack.path_log,"hts-cache/new.zip"));
  707.             if (fexist(fconcat(httrack.path_log,"hts-cache/old.zip")))
  708.               remove(fconcat(httrack.path_log,"hts-cache/old.zip"));
  709.             if (fexist(fconcat(httrack.path_log,"hts-cache/new.dat")))
  710.               remove(fconcat(httrack.path_log,"hts-cache/new.dat"));
  711.             if (fexist(fconcat(httrack.path_log,"hts-cache/new.ndx")))
  712.               remove(fconcat(httrack.path_log,"hts-cache/new.ndx"));
  713.             if (fexist(fconcat(httrack.path_log,"hts-cache/old.dat")))
  714.               remove(fconcat(httrack.path_log,"hts-cache/old.dat"));
  715.             if (fexist(fconcat(httrack.path_log,"hts-cache/old.ndx")))
  716.               remove(fconcat(httrack.path_log,"hts-cache/old.ndx"));
  717.             if (fexist(fconcat(httrack.path_log,"hts-cache/new.lst")))
  718.               remove(fconcat(httrack.path_log,"hts-cache/new.lst"));
  719.             if (fexist(fconcat(httrack.path_log,"hts-cache/old.lst")))
  720.               remove(fconcat(httrack.path_log,"hts-cache/old.lst"));
  721.             if (fexist(fconcat(httrack.path_log,"hts-cache/new.txt")))
  722.               remove(fconcat(httrack.path_log,"hts-cache/new.txt"));
  723.             if (fexist(fconcat(httrack.path_log,"hts-cache/old.txt")))
  724.               remove(fconcat(httrack.path_log,"hts-cache/old.txt"));
  725.             if (fexist(fconcat(httrack.path_log,"hts-cache/doit.log")))
  726.               remove(fconcat(httrack.path_log,"hts-cache/doit.log"));
  727.             if (fexist(fconcat(httrack.path_log,"hts-in_progress.lock")))
  728.               remove(fconcat(httrack.path_log,"hts-in_progress.lock"));
  729.             rmdir(fconcat(httrack.path_log,"hts-cache"));
  730.             //
  731.           } else if (strfield2(argv[i]+2,"catchurl")) {      // capture d'URL via proxy temporaire!
  732.             argv_url=1;     // forcer a passer les parametres
  733.             strcpybuff(argv[i]+1,"#P");
  734.             //
  735.           } else if (strfield2(argv[i]+2,"updatehttrack")) {
  736. #ifdef _WIN32
  737.             char s[HTS_CDLMAXSIZE];
  738.             sprintf(s,"%s not available in this version",argv[i]);
  739.             HTS_PANIC_PRINTF(s);
  740.             htsmain_free();
  741.             return -1;
  742. #else
  743. #if 0
  744.             char _args[8][256];
  745.             char *args[8];
  746.             
  747.             printf("Cheking for updates...\n");
  748.             strcpybuff(_args[0],argv[0]);
  749.             strcpybuff(_args[1],"--get");
  750.             sprintf(_args[2],HTS_UPDATE_WEBSITE,HTS_PLATFORM,"");
  751.             strcpybuff(_args[3],"--quickinfo");
  752.             args[0]=_args[0];
  753.             args[1]=_args[1];
  754.             args[2]=_args[2];
  755.             args[3]=_args[3];
  756.             args[4]=NULL;
  757.             if (execvp(args[0],args)==-1) {
  758.             }
  759. #endif
  760. #endif
  761.           }
  762.           //
  763.           else {
  764.             char s[HTS_CDLMAXSIZE];
  765.             sprintf(s,"%s not recognized",argv[i]);
  766.             HTS_PANIC_PRINTF(s);
  767.             htsmain_free();
  768.             return -1;
  769.           }
  770.  
  771.         } 
  772.       }
  773.     }
  774.   }
  775.  
  776.   // Compter urls/jokers
  777.   /*
  778.   if (argv_url<=0) { 
  779.     int na;
  780.     argv_url=0;
  781.     for(na=1;na<argc;na++) {
  782.       if ( (strcmp(argv[na],"-P")==0) || (strcmp(argv[na],"-N")==0) || (strcmp(argv[na],"-F")==0) || (strcmp(argv[na],"-O")==0) || (strcmp(argv[na],"-V")==0) ) {
  783.         na++;    // sauter nom de proxy
  784.       } else if (!cmdl_opt(argv[na])) { 
  785.         argv_url++;   // un de plus       
  786.       } else if (strcmp(argv[na],"-h")==0) {
  787.         help(argv[0],!httrack.quiet);
  788.         htsmain_free();
  789.         return 0;
  790.       } else {
  791.         if ((strchr(argv[na],'q')!=NULL))
  792.           httrack.quiet=1;    // ne pas poser de questions! (nohup par exemple)
  793.         if ((strchr(argv[na],'i')!=NULL)) {  // doit.log!
  794.           argv_url=0;
  795.           na=argc;
  796.         }
  797.       }
  798.     }
  799.   }  
  800.   */
  801.  
  802.   // Ici on ajoute les arguments qui ont ΘtΘ appelΘs avant au cas o∙ on rΘcupΦre une session
  803.   // Exemple: httrack www.truc.fr -L0 puis ^C puis httrack sans URL : ajouter URL prΘcΘdente
  804.   /*
  805.   if (argv_url==0) {
  806.     //if ((fexist(fconcat(httrack.path_log,"hts-cache/new.dat"))) && (fexist(fconcat(httrack.path_log,"hts-cache/new.ndx")))) {  // il existe dΘja un cache prΘcΘdent.. renommer
  807.     if (fexist(fconcat(httrack.path_log,"hts-cache/doit.log"))) {    // un cache est prΘsent
  808.       
  809.       x_argvblk=(char*) calloct(32768,1);
  810.       
  811.       if (x_argvblk!=NULL) {
  812.         FILE* fp;
  813.         int x_argc;
  814.         
  815.         //strcpybuff(x_argvblk,"httrack ");
  816.         fp=fopen(fconcat(httrack.path_log,"hts-cache/doit.log"),"rb");
  817.         if (fp) {
  818.           linput(fp,x_argvblk+strlen(x_argvblk),8192);
  819.           fclose(fp); fp=NULL;
  820.         }
  821.         
  822.         // calculer arguments selon derniers arguments
  823.         x_argv[0]=argv[0];
  824.         x_argc=1;
  825.         {
  826.           char* p=x_argvblk;
  827.           do {
  828.             x_argv[x_argc++]=p;
  829.             //p=strstr(p," ");
  830.             // exemple de chaine: "echo \"test\"" c:\a "\$0"
  831.             p=next_token(p,1);    // prochain token
  832.             if (p) {
  833.               *p=0;    // octet nul (tableau)
  834.               p++;
  835.             }            
  836.           } while(p!=NULL);
  837.         }
  838.         // recopier arguments actuels (pointeurs uniquement)
  839.         {
  840.           int na;
  841.           for(na=1;na<argc;na++) {
  842.             if (strcmp(argv[na],"-O") != 0)    // SAUF le path!
  843.               x_argv[x_argc++]=argv[na];
  844.             else
  845.               na++;
  846.           }
  847.         }
  848.         argc=x_argc;      // nouvel argc
  849.         argv=x_argv;      // nouvel argv
  850.       }
  851.       
  852.       
  853.     }
  854.     //}
  855.   }
  856.   */
  857.   
  858.   // VΘrifier quiet
  859.   /*
  860.   { 
  861.     int na;    
  862.     for(na=1;na<argc;na++) {
  863.       if (!cmdl_opt(argv[na])) { 
  864.         if ((strcmp(argv[na],"-P")==0) || (strcmp(argv[na],"-N")==0) || (strcmp(argv[na],"-F")==0) || (strcmp(argv[na],"-O")==0) || (strcmp(argv[na],"-V")==0))
  865.           na++;    // sauter nom de proxy
  866.       } else {
  867.         if ((strchr(argv[na],'q')!=NULL) || (strchr(argv[na],'i')!=NULL))
  868.           httrack.quiet=1;    // ne pas poser de questions! (nohup par exemple)
  869.       }
  870.     }
  871.   }
  872.   */
  873.  
  874.   // Pas d'URL
  875. #if DEBUG_STEPS
  876.   printf("Checking URLs\n");
  877. #endif
  878.   if (argv_url==0) {
  879.     // PrΘsence d'un cache, que faire?..
  880.     if (
  881.       ( fexist(fconcat(httrack.path_log,"hts-cache/new.zip")) )
  882.       ||
  883.       ( fexist(fconcat(httrack.path_log,"hts-cache/new.dat")) && fexist(fconcat(httrack.path_log,"hts-cache/new.ndx")) )
  884.       ) {  // il existe dΘja un cache prΘcΘdent.. renommer
  885.       if (fexist(fconcat(httrack.path_log,"hts-cache/doit.log"))) {    // un cache est prΘsent
  886.         if (x_argvblk!=NULL) {
  887.           int m;        
  888.           // Θtablir mode - mode cache: 1 (cache valide) 2 (cache α vΘrifier)
  889.           if (fexist(fconcat(httrack.path_log,"hts-in_progress.lock"))) {    // cache prioritaire
  890.             m=1;
  891.             recuperer=1;
  892.           } else {
  893.             m=2;
  894.           }
  895.           httrack.cache=m;
  896.           
  897.           if (httrack.quiet==0) {  // sinon on continue automatiquement
  898.             HT_REQUEST_START;
  899.             HT_PRINT("A cache (hts-cache/) has been found in the directory ");
  900.             HT_PRINT(httrack.path_log);
  901.             HT_PRINT(LF);
  902.             if (m==1) {
  903.               HT_PRINT("That means that a transfer has been aborted"LF);
  904.               HT_PRINT("OK to Continue ");
  905.             } else {
  906.               HT_PRINT("That means you can update faster the remote site(s)"LF);
  907.               HT_PRINT("OK to Update ");
  908.             }
  909.             HT_PRINT("httrack "); HT_PRINT(x_argvblk); HT_PRINT("?"LF);
  910.             HT_REQUEST_END;
  911.             if (!ask_continue()) { 
  912.               htsmain_free();
  913.               return 0;
  914.             }
  915.           }
  916.           
  917.         } else {
  918.           HTS_PANIC_PRINTF("Error, not enough memory");
  919.           htsmain_free();
  920.           return -1;
  921.         }
  922.       } else { // log existe pas
  923.         HTS_PANIC_PRINTF("A cache has been found, but no command line");
  924.         printf("Please launch httrack with proper parameters to reuse the cache\n");
  925.         htsmain_free();
  926.         return -1;
  927.       }
  928.       
  929.     } else {    // aucune URL dΘfinie et pas de cache
  930.       if (argc > 1 && strcmp(argv[0], "-#h") == 0) {
  931.         printf("HTTrack version "HTTRACK_VERSION"%s\n", WHAT_is_available);
  932.         exit(0);
  933.       }
  934. #if HTS_ANALYSTE!=2
  935.       if (httrack.quiet) {
  936. #endif
  937.         help(argv[0],!httrack.quiet);
  938.         htsmain_free();
  939.         return -1;
  940. #if HTS_ANALYSTE!=2
  941.       } else {
  942.         help_wizard(&httrack);
  943.         htsmain_free();
  944.         return -1;
  945.       }
  946. #endif
  947.       htsmain_free();
  948.       return 0;
  949.     }
  950.   } else {   // plus de 2 paramΦtres
  951.     // un fichier log existe?
  952.     if (fexist(fconcat(httrack.path_log,"hts-in_progress.lock"))) {  // fichier lock?
  953.       //char s[32];
  954.       
  955.       httrack.cache=1;    // cache prioritaire
  956.       if (httrack.quiet==0) {
  957.         if (
  958.           ( fexist(fconcat(httrack.path_log,"hts-cache/new.zip")) )
  959.           ||
  960.           ( fexist(fconcat(httrack.path_log,"hts-cache/new.dat")) && fexist(fconcat(httrack.path_log,"hts-cache/new.ndx")) )
  961.           ) {
  962.           HT_REQUEST_START;
  963.           HT_PRINT("There is a lock-file in the directory ");
  964.           HT_PRINT(httrack.path_log);
  965.           HT_PRINT(LF"That means that a mirror has not been terminated"LF);
  966.           HT_PRINT("Be sure you call httrack with proper parameters"LF);
  967.           HT_PRINT("(The cache allows you to restart faster the transfer)"LF);
  968.           HT_REQUEST_END;
  969.           if (!ask_continue()) {
  970.             htsmain_free();
  971.             return 0;
  972.           }
  973.         }
  974.       }
  975.     } else if (fexist(fconcat(httrack.path_html,"index.html"))) {
  976.       //char s[32];
  977.       httrack.cache=2;  // cache vient aprΦs test de validitΘ
  978.       if (httrack.quiet==0) {
  979.         if (
  980.           ( fexist(fconcat(httrack.path_log,"hts-cache/new.zip")) )
  981.           ||
  982.           ( fexist(fconcat(httrack.path_log,"hts-cache/new.dat")) && fexist(fconcat(httrack.path_log,"hts-cache/new.ndx")) )
  983.           ) {
  984.           HT_REQUEST_START;
  985.           HT_PRINT("There is an index.html and a hts-cache folder in the directory ");
  986.           HT_PRINT(httrack.path_log);
  987.           HT_PRINT(LF"A site may have been mirrored here, that could mean that you want to update it"LF);
  988.           HT_PRINT("Be sure parameters are ok"LF);
  989.           HT_REQUEST_END;
  990.           if (!ask_continue()) {
  991.             htsmain_free();
  992.             return 0;
  993.           }
  994.         } else {
  995.           HT_REQUEST_START;
  996.           HT_PRINT("There is an index.html in the directory ");
  997.           HT_PRINT(httrack.path_log);
  998.           HT_PRINT(" but no cache"LF);
  999.           HT_PRINT("There is an index.html in the directory, but no cache"LF);
  1000.           HT_PRINT("A site may have been mirrored here, and erased.."LF);
  1001.           HT_PRINT("Be sure parameters are ok"LF);
  1002.           HT_REQUEST_END;
  1003.           if (!ask_continue()) {
  1004.             htsmain_free();
  1005.             return 0;
  1006.           }
  1007.         }
  1008.       }
  1009.     }
  1010.   }
  1011.   
  1012.   
  1013.   // Treat parameters
  1014.   // Traiter les paramΦtres
  1015. #if DEBUG_STEPS
  1016.   printf("Analyze parameters\n");
  1017. #endif
  1018.   { 
  1019.     char* com;
  1020.     int na;
  1021.     
  1022.     for(na=1;na<argc;na++) {
  1023.  
  1024.       if (argv[na][0]=='"') {
  1025.         char BIGSTK tempo[HTS_CDLMAXSIZE];
  1026.         strcpybuff(tempo,argv[na]+1);
  1027.         if (tempo[strlen(tempo)-1]!='"') {
  1028.           char s[HTS_CDLMAXSIZE];
  1029.           sprintf(s,"Missing quote in %s",argv[na]);
  1030.           HTS_PANIC_PRINTF(s);
  1031.           htsmain_free();
  1032.           return -1;
  1033.         }
  1034.         tempo[strlen(tempo)-1]='\0';
  1035.         strcpybuff(argv[na],tempo);
  1036.       }
  1037.  
  1038.       if (cmdl_opt(argv[na])) { // option
  1039.         com=argv[na]+1;
  1040.         
  1041.         while(*com) {
  1042.           switch(*com) {
  1043.           case ' ': case 9: case '-': case '\0': break;
  1044.             //
  1045.           case 'h': 
  1046.             help(argv[0],0); 
  1047.             htsmain_free();
  1048.             return 0;   // dΘja fait normalement
  1049.             //
  1050.           case 'g':    // rΘcupΘrer un (ou plusieurs) fichiers isolΘs
  1051.             httrack.wizard=2;             // le wizard on peut plus s'en passer..
  1052.             //httrack.wizard=0;             // pas de wizard
  1053.             httrack.cache=0;              // ni de cache
  1054.             httrack.makeindex=0;          // ni d'index
  1055.             httrack_logmode=1;            // erreurs α l'Θcran
  1056.             httrack.savename_type=1003;   // mettre dans le rΘpertoire courant
  1057.             httrack.depth=0;              // ne pas explorer la page
  1058.             httrack.accept_cookie=0;      // pas de cookies
  1059.             httrack.robots=0;             // pas de robots
  1060.             break;
  1061.           case 'w': httrack.wizard=2;    // wizard 'soft' (ne pose pas de questions)
  1062.             httrack.travel=0;
  1063.             httrack.seeker=1;
  1064.             break;
  1065.           case 'W': httrack.wizard=1;    // Wizard-Help (pose des questions)
  1066.             httrack.travel=0;
  1067.             httrack.seeker=1;
  1068.             break;
  1069.           case 'r':                      // n'est plus le recurse get bestial mais wizard itou!
  1070.             if (isdigit((unsigned char)*(com+1))) {
  1071.               sscanf(com+1,"%d",&httrack.depth);
  1072.               while(isdigit((unsigned char)*(com+1))) com++;
  1073.             } else httrack.depth=3;
  1074.             break;
  1075. /*
  1076.           case 'r': httrack.wizard=0;
  1077.             if (isdigit((unsigned char)*(com+1))) {
  1078.               sscanf(com+1,"%d",&httrack.depth);
  1079.               while(isdigit((unsigned char)*(com+1))) com++;
  1080.             } else httrack.depth=3;
  1081.             break;
  1082. */
  1083.             //
  1084.             // note: les tests httrack.depth sont pour Θviter de faire
  1085.             // un miroir du web (:-O) accidentelement ;-)
  1086.           case 'a': /*if (httrack.depth==9999) httrack.depth=3;*/
  1087.             httrack.travel=0+(httrack.travel&256); break;
  1088.           case 'd': /*if (httrack.depth==9999) httrack.depth=3;*/
  1089.             httrack.travel=1+(httrack.travel&256); break;
  1090.           case 'l': /*if (httrack.depth==9999) httrack.depth=3;*/
  1091.             httrack.travel=2+(httrack.travel&256); break;
  1092.           case 'e': /*if (httrack.depth==9999) httrack.depth=3;*/
  1093.             httrack.travel=7+(httrack.travel&256); break;
  1094.           case 't': httrack.travel|=256; break;
  1095.           case 'n': httrack.nearlink=1; break;
  1096.           case 'x': httrack.external=1; break;
  1097.             //
  1098.           case 'U': httrack.seeker=2; break;
  1099.           case 'D': httrack.seeker=1; break;
  1100.           case 'S': httrack.seeker=0; break;
  1101.           case 'B': httrack.seeker=3; break;
  1102.             //
  1103.           case 'Y': httrack.mirror_first_page=1; break;
  1104.             //
  1105.           case 'q': case 'i': httrack.quiet=1; break;
  1106.             //
  1107.           case 'Q': httrack_logmode=0; break;
  1108.           case 'v': httrack_logmode=1; break;
  1109.           case 'f': httrack_logmode=2; if (*(com+1)=='2') httrack_logmode=3; while(isdigit((unsigned char)*(com+1))) com++; break;
  1110.             //
  1111.           //case 'A': httrack.urlmode=1; break;
  1112.           //case 'R': httrack.urlmode=2; break;
  1113.           case 'K': httrack.urlmode=0; 
  1114.             if (isdigit((unsigned char)*(com+1))) {
  1115.               sscanf(com+1,"%d",&httrack.urlmode);
  1116.               if (httrack.urlmode == 0) {  // in fact K0 ==> K2
  1117.                                            // and K ==> K0
  1118.                 httrack.urlmode=2;
  1119.               }
  1120.               while(isdigit((unsigned char)*(com+1))) com++; 
  1121.             }
  1122.             //if (*(com+1)=='0') { httrack.urlmode=2; com++; } break;
  1123.             //
  1124.           case 'c':
  1125.             if (isdigit((unsigned char)*(com+1))) {
  1126.               sscanf(com+1,"%d",&httrack.maxsoc);
  1127.               while(isdigit((unsigned char)*(com+1))) com++;
  1128.               httrack.maxsoc=max(httrack.maxsoc,1);     // FORCER A 1
  1129.             } else httrack.maxsoc=4;
  1130.             
  1131.             break;
  1132.             //
  1133.           case 'p': sscanf(com+1,"%d",&httrack.getmode); while(isdigit((unsigned char)*(com+1))) com++; break;
  1134.             //        
  1135.           case 'G': sscanf(com+1,LLintP,&httrack.fragment); while(isdigit((unsigned char)*(com+1))) com++; break;
  1136.           case 'M': sscanf(com+1,LLintP,&httrack.maxsite); while(isdigit((unsigned char)*(com+1))) com++; break;
  1137.           case 'm': sscanf(com+1,LLintP,&httrack.maxfile_nonhtml); while(isdigit((unsigned char)*(com+1))) com++; 
  1138.             if (*(com+1)==',') {
  1139.               com++;
  1140.               sscanf(com+1,LLintP,&httrack.maxfile_html); while(isdigit((unsigned char)*(com+1))) com++;
  1141.             } else httrack.maxfile_html=-1;
  1142.             break;
  1143.             //
  1144.           case 'T': sscanf(com+1,"%d",&httrack.timeout); while(isdigit((unsigned char)*(com+1))) com++; break;
  1145.           case 'J': sscanf(com+1,"%d",&httrack.rateout); while(isdigit((unsigned char)*(com+1))) com++; break;
  1146.           case 'R': sscanf(com+1,"%d",&httrack.retry); while(isdigit((unsigned char)*(com+1))) com++; break;
  1147.           case 'E': sscanf(com+1,"%d",&httrack.maxtime); while(isdigit((unsigned char)*(com+1))) com++; break;
  1148.           case 'H': sscanf(com+1,"%d",&httrack.hostcontrol); while(isdigit((unsigned char)*(com+1))) com++; break;
  1149.           case 'A': sscanf(com+1,"%d",&httrack.maxrate); while(isdigit((unsigned char)*(com+1))) com++; break;
  1150.  
  1151.           case 'j': httrack.parsejava=1; if (*(com+1)=='0') { httrack.parsejava=0; com++; } break;
  1152.             //
  1153.           case 'I': httrack.makeindex=1; if (*(com+1)=='0') { httrack.makeindex=0; com++; } break;
  1154.             //
  1155.           case 'X': httrack.delete_old=1; if (*(com+1)=='0') { httrack.delete_old=0; com++; } break;
  1156.             //
  1157.           case 'b': sscanf(com+1,"%d",&httrack.accept_cookie); while(isdigit((unsigned char)*(com+1))) com++; break;
  1158.             //
  1159.           case 'N':
  1160.             if (strcmp(argv[na],"-N")==0) {    // Tout seul
  1161.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {  // erreur
  1162.                 HTS_PANIC_PRINTF("Option N needs a number, or needs to be followed by a blank space, and a string");
  1163.                 printf("Example: -N4\n");
  1164.                 htsmain_free();
  1165.                 return -1;
  1166.               } else {
  1167.                 na++;
  1168.                 if (strlen(argv[na])>=127) {
  1169.                   HTS_PANIC_PRINTF("Userdef structure string too long");
  1170.                   htsmain_free();
  1171.                   return -1;
  1172.                 }
  1173.                 strcpybuff(httrack.savename_userdef,argv[na]);
  1174.                 if (strnotempty(httrack.savename_userdef))
  1175.                   httrack.savename_type = -1;    // userdef!
  1176.                 else
  1177.                   httrack.savename_type = 0;    // -N "" : par dΘfaut
  1178.               }
  1179.             } else {
  1180.               sscanf(com+1,"%d",&httrack.savename_type); while(isdigit((unsigned char)*(com+1))) com++;
  1181.             }
  1182.             break;
  1183.           case 'L': 
  1184.             {
  1185.               sscanf(com+1,"%d",&httrack.savename_83); 
  1186.               switch(httrack.savename_83) {
  1187.               case 0:    // 8-3 (ISO9660 L1)
  1188.                 httrack.savename_83=1;
  1189.                 break;
  1190.               case 1:
  1191.                 httrack.savename_83=0;
  1192.                 break;
  1193.               default:    // 2 == ISO9660 (ISO9660 L2)
  1194.                 httrack.savename_83=2;
  1195.                 break;
  1196.               }
  1197.               while(isdigit((unsigned char)*(com+1))) com++; 
  1198.             }
  1199.             break;
  1200.           case 's': 
  1201.             if (isdigit((unsigned char)*(com+1))) {
  1202.               sscanf(com+1,"%d",&httrack.robots);
  1203.               while(isdigit((unsigned char)*(com+1))) com++;
  1204.             } else httrack.robots=1;
  1205. #if DEBUG_ROBOTS
  1206.             printf("robots.txt mode set to %d\n",httrack.robots);
  1207. #endif
  1208.             break;
  1209.           case 'o': sscanf(com+1,"%d",&httrack.errpage); while(isdigit((unsigned char)*(com+1))) com++; break;
  1210.           case 'u': sscanf(com+1,"%d",&httrack.check_type); while(isdigit((unsigned char)*(com+1))) com++; break;
  1211.             //
  1212.           case 'C': 
  1213.             if (isdigit((unsigned char)*(com+1))) {
  1214.               sscanf(com+1,"%d",&httrack.cache);
  1215.               while(isdigit((unsigned char)*(com+1))) com++;
  1216.             } else httrack.cache=1;
  1217.             break;
  1218.           case 'k': httrack.all_in_cache=1; break;
  1219.             //
  1220.           case 'z': httrack.debug=1; break;  // petit debug
  1221.           case 'Z': httrack.debug=2; break;  // GROS debug
  1222.             //
  1223.           case '&': case '%': {    // deuxiΦme jeu d'options
  1224.             com++;
  1225.             switch(*com) {
  1226.             case 'M': httrack.mimehtml = 1; if (*(com+1)=='0') { httrack.mimehtml=0; com++; } break;
  1227.             case 'k': httrack.nokeepalive = 0; if (*(com+1)=='0') { httrack.nokeepalive = 1; com++; } break;
  1228.             case 'x': httrack.passprivacy=1; if (*(com+1)=='0') { httrack.passprivacy=0; com++; } break;   // No passwords in html files
  1229.             case 'q': httrack.includequery=1; if (*(com+1)=='0') { httrack.includequery=0; com++; } break;   // No passwords in html files
  1230.             case 'I': httrack.kindex=1; if (isdigit((unsigned char)*(com+1))) { sscanf(com+1,"%d",&httrack.kindex); while(isdigit((unsigned char)*(com+1))) com++; }
  1231.               break;    // Keyword Index
  1232.             case 'c': sscanf(com+1,"%f",&httrack.maxconn); while(isdigit((unsigned char)*(com+1)) || *(com+1) == '.') com++; break;
  1233.             case 'e': sscanf(com+1,"%d",&httrack.extdepth); while(isdigit((unsigned char)*(com+1))) com++; break;
  1234.             case 'B': httrack.tolerant=1; if (*(com+1)=='0') { httrack.tolerant=0; com++; } break;   // HTTP/1.0 notamment
  1235.             case 'h': httrack.http10=1; if (*(com+1)=='0') { httrack.http10=0; com++; } break;   // HTTP/1.0
  1236.             case 'z': httrack.nocompression=1; if (*(com+1)=='0') { httrack.nocompression=0; com++; } break;   // pas de compression
  1237.             case 'f': httrack.ftp_proxy=1; if (*(com+1)=='0') { httrack.ftp_proxy=0; com++; } break;   // proxy http pour ftp
  1238.             case 'P': httrack.parseall=1; if (*(com+1)=='0') { httrack.parseall=0; com++; } break;   // tout parser
  1239.             case 'n': httrack.norecatch=1; if (*(com+1)=='0') { httrack.norecatch=0; com++; } break;   // ne pas reprendre fichiers effacΘs localement
  1240.             case 's': httrack.sizehack=1; if (*(com+1)=='0') { httrack.sizehack=0; com++; } break;   // hack sur content-length
  1241.             case 'u': httrack.urlhack=1; if (*(com+1)=='0') { httrack.urlhack=0; com++; } break;   // url hack
  1242.             case 'v': httrack.verbosedisplay=2; if (isdigit((unsigned char)*(com+1))) { sscanf(com+1,"%d",&httrack.verbosedisplay); while(isdigit((unsigned char)*(com+1))) com++; } break;
  1243.             case 'i': httrack.dir_topindex = 1; if (*(com+1)=='0') { httrack.dir_topindex=0; com++; } break;
  1244.             case 'N': httrack.savename_delayed = 2; if (isdigit((unsigned char)*(com+1))) { sscanf(com+1,"%d",&httrack.savename_delayed); while(isdigit((unsigned char)*(com+1))) com++; } break;
  1245.             case 'D': httrack.delayed_cached=1; if (*(com+1)=='0') { httrack.delayed_cached=0; com++; } break;   // url hack
  1246.             case '!': httrack.bypass_limits = 1; if (*(com+1)=='0') { httrack.bypass_limits=0; com++; } break;
  1247. #if HTS_USEMMS
  1248.                         case 'm': sscanf(com+1,"%d",&httrack.mms_maxtime); while(isdigit((unsigned char)*(com+1))) com++; break;
  1249. #endif
  1250.  
  1251.             // preserve: no footer, original links
  1252.             case 'p':
  1253.               httrack.footer[0]='\0';
  1254.               httrack.urlmode=4;
  1255.               break;
  1256.             case 'L':    // URL list
  1257.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1258.                 HTS_PANIC_PRINTF("Option %L needs to be followed by a blank space, and a text filename");
  1259.                 printf("Example: -%%L \"mylist.txt\"\n");
  1260.                 htsmain_free();
  1261.                 return -1;
  1262.               } else{
  1263.                 na++;
  1264.                 if (strlen(argv[na])>=254) {
  1265.                   HTS_PANIC_PRINTF("File list string too long");
  1266.                   htsmain_free();
  1267.                   return -1;
  1268.                 }
  1269.                 strcpybuff(httrack.filelist,argv[na]);
  1270.               }
  1271.               break;
  1272.             case 'b':  // bind
  1273.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1274.                 HTS_PANIC_PRINTF("Option %b needs to be followed by a blank space, and a local hostname");
  1275.                 printf("Example: -%%b \"ip4.localhost\"\n");
  1276.                 htsmain_free();
  1277.                 return -1;
  1278.               } else{
  1279.                 na++;
  1280.                 if (strlen(argv[na])>=254) {
  1281.                   HTS_PANIC_PRINTF("Hostname string too long");
  1282.                   htsmain_free();
  1283.                   return -1;
  1284.                 }
  1285.                 strcpybuff(httrack.proxy.bindhost,argv[na]);
  1286.               }
  1287.               break;
  1288.             case 'S':    // Scan Rules list
  1289.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1290.                 HTS_PANIC_PRINTF("Option %S needs to be followed by a blank space, and a text filename");
  1291.                 printf("Example: -%%S \"myfilterlist.txt\"\n");
  1292.                 htsmain_free();
  1293.                 return -1;
  1294.               } else{
  1295.                 INTsys fz;
  1296.                 na++;
  1297.                 fz = fsize(argv[na]);
  1298.                 if (fz < 0) {
  1299.                   HTS_PANIC_PRINTF("File url list could not be opened");
  1300.                   htsmain_free();
  1301.                   return -1;
  1302.                 } else {
  1303.                   FILE* fp = fopen(argv[na], "rb");
  1304.                   if (fp != NULL) {
  1305.                     int cl = (int) strlen(url);
  1306.                     ensureUrlCapacity(url, url_sz, cl + fz + 8192);
  1307.                     if ((INTsys)fread(url + cl, 1, fz, fp) != fz) {
  1308.                       HTS_PANIC_PRINTF("File url list could not be read");
  1309.                       htsmain_free();
  1310.                       return -1;
  1311.                     }
  1312.                     fclose(fp);
  1313.                     *(url + cl + fz) = '\0';
  1314.                   }
  1315.                 }
  1316.               }
  1317.               break;
  1318.             case 'A':    // assume
  1319.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1320.                 HTS_PANIC_PRINTF("Option %A needs to be followed by a blank space, and a filesystemtype=mimetype/mimesubtype parameters");
  1321.                 printf("Example: -%%A php3=text/html,asp=text/html\n");
  1322.                 htsmain_free();
  1323.                 return -1;
  1324.               } else{
  1325.                 na++;
  1326.                 if ( (strlen(argv[na]) + strlen(httrack.mimedefs) + 4) >= sizeof(httrack.mimedefs)) {
  1327.                   HTS_PANIC_PRINTF("Mime definition string too long");
  1328.                   htsmain_free();
  1329.                   return -1;
  1330.                 }
  1331.                 // --assume standard
  1332.                 if (strcmp(argv[na], "standard") == 0) {
  1333.                   strcpybuff(httrack.mimedefs,"\n");
  1334.                   strcatbuff(httrack.mimedefs,HTS_ASSUME_STANDARD);
  1335.                   strcatbuff(httrack.mimedefs,"\n");
  1336.                 } else {
  1337.                   char* a;
  1338.                   char* b = httrack.mimedefs + strlen(httrack.mimedefs);
  1339.                   for(a = argv[na] ; *a != '\0' ; a++) {
  1340.                     if (*a == ';') {    /* next one */
  1341.                       *b++ = '\n';
  1342.                     } else if (*a == ',' || *a == '\n' || *a == '\r' || *a == '\t') {
  1343.                       *b++ = ' ';
  1344.                     } else {
  1345.                       *b++ = *a;
  1346.                     }
  1347.                   }
  1348.                   *b++ = '\n';    /* next def */
  1349.                   *b++ = '\0';
  1350.                 }
  1351.               }
  1352.               break;
  1353.               //
  1354.             case 'l': 
  1355.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1356.                 HTS_PANIC_PRINTF("Option %l needs to be followed by a blank space, and an ISO language code");
  1357.                 printf("Example: -%%l \"en\"\n");
  1358.                 htsmain_free();
  1359.                 return -1;
  1360.               } else{
  1361.                 na++;
  1362.                 if (strlen(argv[na])>=62) {
  1363.                   HTS_PANIC_PRINTF("Lang list string too long");
  1364.                   htsmain_free();
  1365.                   return -1;
  1366.                 }
  1367.                 strcpybuff(httrack.lang_iso,argv[na]);
  1368.               }
  1369.               break;
  1370.               //
  1371.             case 'F':     // footer id
  1372.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1373.                 HTS_PANIC_PRINTF("Option %F needs to be followed by a blank space, and a footer string");
  1374.                 printf("Example: -%%F \"<!-- Mirrored from %%s by HTTrack Website Copier/"HTTRACK_AFF_VERSION" "HTTRACK_AFF_AUTHORS", %%s -->\"\n");
  1375.                 htsmain_free();
  1376.                 return -1;
  1377.               } else{
  1378.                 na++;
  1379.                 if (strlen(argv[na])>=254) {
  1380.                   HTS_PANIC_PRINTF("Footer string too long");
  1381.                   htsmain_free();
  1382.                   return -1;
  1383.                 }
  1384.                 strcpybuff(httrack.footer,argv[na]);
  1385.               }
  1386.               break;
  1387.             case 'H':                 // debug headers
  1388.               _DEBUG_HEAD=1;
  1389.               break;
  1390.             case 'O':
  1391. #if HTS_WIN
  1392.               printf("Warning option -%%O has no effect in this system (chroot)\n");
  1393. #else
  1394.               switch_chroot=1;
  1395. #endif
  1396.               break;
  1397.             case 'U':                 // setuid
  1398.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1399.                 HTS_PANIC_PRINTF("Option %U needs to be followed by a blank space, and a username");
  1400.                 printf("Example: -%%U smith\n");
  1401.                 htsmain_free();
  1402.                 return -1;
  1403.               } else {
  1404.                 na++;
  1405. #if HTS_WIN
  1406.                 printf("Warning option -%%U has no effect on this system (setuid)\n");
  1407. #else
  1408. #ifndef HTS_DO_NOT_USE_UID
  1409.                 /* Change the user id and gid */
  1410.                 {
  1411.                   struct passwd* userdef=getpwnam((const char*)argv[na]);
  1412.                   if (userdef) {    /* we'll have to switch the user id */
  1413.                     switch_gid=userdef->pw_gid;
  1414.                     switch_uid=userdef->pw_uid;
  1415.                   }
  1416.                 }
  1417. #else
  1418.                 printf("Warning option -%%U has no effect with this compiled version (setuid)\n");
  1419. #endif
  1420. #endif
  1421.               }
  1422.               break;
  1423.               
  1424.             case 'W':       // Wrapper callback
  1425.               // --wrapper check-link=obj.so:check_link
  1426.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1427.                 HTS_PANIC_PRINTF("Option %W needs to be followed by a blank space, and a <callback-name>=<myfile.so>:<function-name> field");
  1428.                 printf("Example: -%%W check-link=checklink.so:check\n");
  1429.                 htsmain_free();
  1430.                 return -1;
  1431.               } else {
  1432.                 char callbackname[128];
  1433.                 char* a = argv[na + 1];
  1434.                 char* pos = strchr(a, '=');
  1435.                 na++;
  1436.                 if (pos != NULL && (pos - a) > 0 && (pos - a + 2) < sizeof(callbackname)) {
  1437.                   char* posf = strchr(pos + 1, ':');
  1438.                   char BIGSTK filename[1024];
  1439.                   callbackname[0] = '\0';
  1440.                   strncatbuff(callbackname, a, pos - a);
  1441.                   pos++;
  1442.                   if (posf != NULL && (posf - pos) > 0 && (posf - pos + 2) < sizeof(filename)) {
  1443.                     void* userfunction;
  1444.                     filename[0] = '\0';
  1445.                     strncatbuff(filename, pos, posf - pos);
  1446.                     posf++;
  1447.                     userfunction = getFunctionPtr(&httrack, filename, posf);
  1448.                     if (userfunction != NULL) {
  1449.                       if ((void*)htswrap_read(callbackname) != NULL) {
  1450.                         if (htswrap_add(callbackname, userfunction)) {
  1451.                           set_wrappers();        /* Re-read wrappers internal static functions */
  1452.                           if ((void*)htswrap_read(callbackname) == userfunction) {
  1453.                             if (!httrack.quiet) {
  1454.                               fprintf(stderr, "successfully plugged [%s -> %s:%s]\n", callbackname, posf, filename);
  1455.                             }
  1456.                           } else {
  1457.                             char BIGSTK tmp[1024 * 2];
  1458.                             sprintf(tmp, "option %%W : unable to (re)plug the function %s from the file %s for the callback %s", posf, filename, callbackname);
  1459.                             HTS_PANIC_PRINTF(tmp);
  1460.                             htsmain_free();
  1461.                             return -1;
  1462.                           }
  1463.                         } else {
  1464.                           char BIGSTK tmp[1024 * 2];
  1465.                           sprintf(tmp, "option %%W : unable to plug the function %s from the file %s for the callback %s", posf, filename, callbackname);
  1466.                           HTS_PANIC_PRINTF(tmp);
  1467.                           htsmain_free();
  1468.                           return -1;
  1469.                         }
  1470.                       } else {
  1471.                         char BIGSTK tmp[1024 * 2];
  1472.                         sprintf(tmp, "option %%W : unknown or undefined callback %s", callbackname);
  1473.                         HTS_PANIC_PRINTF(tmp);
  1474.                         htsmain_free();
  1475.                         return -1;
  1476.                       }
  1477.                     } else {
  1478.                       char BIGSTK tmp[1024 * 2];
  1479.                       sprintf(tmp, "option %%W : unable to load the function %s in the file %s for the callback %s", posf, filename, callbackname);
  1480.                       HTS_PANIC_PRINTF(tmp);
  1481.                       htsmain_free();
  1482.                       return -1;
  1483.                     }
  1484.                   } else {
  1485.                     HTS_PANIC_PRINTF("Syntax error in option %W : filename error : this function needs to be followed by a blank space, and a <callback-name>=<myfile.so>:<function-name> field");
  1486.                     printf("Example: -%%W check-link=checklink.so:check\n");
  1487.                     htsmain_free();
  1488.                     return -1;
  1489.                   }
  1490.                 } else {
  1491.                   HTS_PANIC_PRINTF("Syntax error in option %W : this function needs to be followed by a blank space, and a <callback-name>=<myfile.so>:<function-name> field");
  1492.                   printf("Example: -%%W check-link=checklink.so:check\n");
  1493.                   htsmain_free();
  1494.                   return -1;
  1495.                 }
  1496.               }
  1497.               break;
  1498.               
  1499.             case 'R':    // Referer
  1500.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1501.                 HTS_PANIC_PRINTF("Option %R needs to be followed by a blank space, and a referer URL");
  1502.                 printf("Example: -%%R \"http://www.example.com/\"\n");
  1503.                 htsmain_free();
  1504.                 return -1;
  1505.               } else{
  1506.                 na++;
  1507.                 if (strlen(argv[na])>=254) {
  1508.                   HTS_PANIC_PRINTF("Referer URL too long");
  1509.                   htsmain_free();
  1510.                   return -1;
  1511.                 }
  1512.                 strcpybuff(httrack.referer, argv[na]);
  1513.               }
  1514.               break;
  1515.             case 'E':    // From Email address
  1516.               if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1517.                 HTS_PANIC_PRINTF("Option %E needs to be followed by a blank space, and an email");
  1518.                 printf("Example: -%%E \"postmaster@example.com\"\n");
  1519.                 htsmain_free();
  1520.                 return -1;
  1521.               } else{
  1522.                 na++;
  1523.                 if (strlen(argv[na])>=254) {
  1524.                   HTS_PANIC_PRINTF("From email too long");
  1525.                   htsmain_free();
  1526.                   return -1;
  1527.                 }
  1528.                 strcpybuff(httrack.from, argv[na]);
  1529.               }
  1530.               break;
  1531.  
  1532.             default: {
  1533.               char s[HTS_CDLMAXSIZE];
  1534.               sprintf(s,"invalid option %%%c\n",*com);
  1535.               HTS_PANIC_PRINTF(s);
  1536.               htsmain_free();
  1537.               return -1;
  1538.                      }
  1539.               break;
  1540.               
  1541.             }
  1542.                     }
  1543.             break;
  1544.             //
  1545.           case '@': {    // troisiΦme jeu d'options
  1546.             com++;
  1547.             switch(*com) {
  1548.             case 'i': 
  1549. #if HTS_INET6==0
  1550.               printf("Warning, option @i has no effect (v6 routines not compiled)\n");
  1551. #else 
  1552.               {
  1553.                 int res=0;
  1554.                 if (isdigit((unsigned char)*(com+1))) {
  1555.                   sscanf(com+1,"%d",&res); while(isdigit((unsigned char)*(com+1))) com++; 
  1556.                 }
  1557.                 switch(res) {
  1558.                 case 1:
  1559.                 case 4:
  1560.                   IPV6_resolver=1;
  1561.                   break;
  1562.                 case 2:
  1563.                 case 6:
  1564.                   IPV6_resolver=2;
  1565.                   break;
  1566.                 case 0:
  1567.                   IPV6_resolver=0;
  1568.                   break;
  1569.                 default:
  1570.                   printf("Unknown flag @i%d\n", res);
  1571.                   htsmain_free();
  1572.                   return -1;
  1573.                   break;
  1574.                 }
  1575.               }
  1576. #endif
  1577.               break;
  1578.               
  1579.                 default: {
  1580.                   char s[HTS_CDLMAXSIZE];
  1581.                   sprintf(s,"invalid option %%%c\n",*com);
  1582.                   HTS_PANIC_PRINTF(s);
  1583.                   htsmain_free();
  1584.                   return -1;
  1585.                          }
  1586.                   break;
  1587.                   
  1588.                   //case 's': httrack.sslengine=1; if (isdigit((unsigned char)*(com+1))) { sscanf(com+1,"%d",&httrack.sslengine); while(isdigit((unsigned char)*(com+1))) com++; } break;
  1589.             }
  1590.                     }
  1591.             break;
  1592.             
  1593.             //
  1594.           case '#':  { // non documentΘ
  1595.             com++;
  1596.             switch(*com) {
  1597.             case 'C':   // list cache files : httrack -#C '*spid*.gif' will attempt to find the matching file
  1598.               {
  1599.                 int hasFilter = 0;
  1600.                 int found = 0;
  1601.                 char* filter=NULL;
  1602.                 cache_back cache;
  1603.                 inthash cache_hashtable=inthash_new(HTS_HASH_SIZE);
  1604.                 int backupXFR = htsMemoryFastXfr;
  1605.                 int sendb = 0;
  1606.                 if (isdigit((unsigned char)*(com+1))) {
  1607.                   sscanf(com+1,"%d",&sendb);
  1608.                   while(isdigit((unsigned char)*(com+1))) com++;
  1609.                 } else sendb=0;
  1610.                 if (!((na+1>=argc) || (argv[na+1][0]=='-'))) {
  1611.                   na++;
  1612.                   hasFilter = 1;
  1613.                   filter=argv[na];
  1614.                 }
  1615.                 htsMemoryFastXfr = 1;               /* fast load */
  1616.  
  1617.                 memset(&cache, 0, sizeof(cache_back));
  1618.                 cache.type=1;       // cache?
  1619.                 cache.log=stdout;     // log?
  1620.                 cache.errlog=stderr;  // err log?
  1621.                 cache.ptr_ant=cache.ptr_last=0;   // pointeur pour anticiper
  1622.                 cache.hashtable=(void*)cache_hashtable;      /* copy backcache hash */
  1623.                 cache.ro = 1;          /* read only */
  1624.                 if (cache.hashtable) {
  1625.                   char BIGSTK adr[HTS_URLMAXSIZE*2];
  1626.                   char BIGSTK fil[HTS_URLMAXSIZE*2];
  1627.                   char BIGSTK url[HTS_URLMAXSIZE*2];
  1628.                   char linepos[256];
  1629.                   int  pos;
  1630.                   char* cacheNdx = readfile(fconcat(httrack.path_log,"hts-cache/new.ndx"));
  1631.                   cache_init(&cache,&httrack);            /* load cache */
  1632.                   if (cacheNdx != NULL) {
  1633.                     char firstline[256];
  1634.                     char* a = cacheNdx;
  1635.                     a+=cache_brstr(a, firstline);
  1636.                     a+=cache_brstr(a, firstline);
  1637.                     while ( a != NULL ) {
  1638.                       a=strchr(a+1,'\n');     /* start of line */
  1639.                       if (a) {
  1640.                         htsblk r;
  1641.                         /* */
  1642.                         a++;
  1643.                         /* read "host/file" */
  1644.                         a+=binput(a,adr,HTS_URLMAXSIZE);
  1645.                         a+=binput(a,fil,HTS_URLMAXSIZE);
  1646.                         url[0]='\0';
  1647.                         if (!link_has_authority(adr))
  1648.                           strcatbuff(url, "http://");
  1649.                         strcatbuff(url, adr);
  1650.                         strcatbuff(url, fil);
  1651.                         /* read position */
  1652.                         a+=binput(a,linepos,200);
  1653.                         sscanf(linepos,"%d",&pos);
  1654.                         if (!hasFilter
  1655.                           ||
  1656.                           (strjoker(url, filter, NULL, NULL) != NULL)
  1657.                           ) {
  1658.                           r = cache_read_ro(&httrack, &cache, adr, fil, "", NULL);    // lire entrΘe cache + data
  1659.                           if (r.statuscode != -1) {    // No errors
  1660.                             found++;
  1661.                             if (!hasFilter) {
  1662.                               fprintf(stdout, "%s%s%s\r\n", 
  1663.                                 (link_has_authority(adr)) ? "" : "http://", 
  1664.                                 adr, fil);
  1665.                             } else {
  1666.                               char msg[256], cdate[256];
  1667.                               char BIGSTK sav[HTS_URLMAXSIZE*2];
  1668.                               infostatuscode(msg, r.statuscode);
  1669.                               time_gmt_rfc822(cdate);
  1670.  
  1671.                               fprintf(stdout, "HTTP/1.1 %d %s\r\n",
  1672.                                 r.statuscode,
  1673.                                 r.msg[0] ? r.msg : msg
  1674.                                 );
  1675.                               fprintf(stdout, "X-Host: %s\r\n", adr);
  1676.                               fprintf(stdout, "X-File: %s\r\n", fil);
  1677.                               fprintf(stdout, "X-URL: %s%s%s\r\n", 
  1678.                                 (link_has_authority(adr)) ? "" : "http://", 
  1679.                                 adr, fil);
  1680.                               if (url_savename(adr, fil, sav, /*former_adr*/NULL, /*former_fil*/NULL, /*referer_adr*/NULL, /*referer_fil*/NULL,
  1681.                                 /*opt*/&httrack, /*liens*/NULL, /*lien_tot*/0, /*sback*/NULL, /*cache*/&cache, /*hash*/NULL, /*ptr*/0, /*numero_passe*/0, /*mime_type*/NULL)!=-1) {
  1682.                                 if (fexist(sav)) {
  1683.                                   fprintf(stdout, "Content-location: %s\r\n", sav);
  1684.                                 }
  1685.                               }
  1686.                               fprintf(stdout, "Date: %s\r\n", cdate);
  1687.                               fprintf(stdout, "Server: HTTrack Website Copier/"HTTRACK_VERSION"\r\n");
  1688.                               if (r.lastmodified[0]) {
  1689.                                 fprintf(stdout, "Last-Modified: %s\r\n", r.lastmodified);
  1690.                               }
  1691.                               if (r.etag[0]) {
  1692.                                 fprintf(stdout, "Etag: %s\r\n", r.etag);
  1693.                               }
  1694.                               if (r.totalsize >= 0) {
  1695.                                 fprintf(stdout, "Content-Length: "LLintP"\r\n", r.totalsize);
  1696.                               }
  1697.                               fprintf(stdout, "X-Content-Length: "LLintP"\r\n", (r.size >= 0) ? r.size : (-r.size) );
  1698.                               if (r.contenttype >= 0) {
  1699.                                 fprintf(stdout, "Content-Type: %s\r\n", r.contenttype);
  1700.                               }
  1701.                               if (r.cdispo[0]) {
  1702.                                 fprintf(stdout, "Content-Disposition: %s\r\n", r.cdispo);
  1703.                               }
  1704.                               if (r.contentencoding[0]) {
  1705.                                 fprintf(stdout, "Content-Encoding: %s\r\n", r.contentencoding);
  1706.                               }
  1707.                               if (r.is_chunk) {
  1708.                                 fprintf(stdout, "Transfer-Encoding: chunked\r\n");
  1709.                               }
  1710. #if HTS_USEOPENSSL
  1711.                               if (r.ssl) {
  1712.                                 fprintf(stdout, "X-SSL: yes\r\n");
  1713.                               }
  1714. #endif
  1715.                               if (r.is_write) {
  1716.                                 fprintf(stdout, "X-Direct-To-Disk: yes\r\n");
  1717.                               }
  1718.                               if (r.compressed) {
  1719.                                 fprintf(stdout, "X-Compressed: yes\r\n");
  1720.                               }
  1721.                               if (r.notmodified) {
  1722.                                 fprintf(stdout, "X-Not-Modified: yes\r\n");
  1723.                               }
  1724.                               if (r.is_chunk) {
  1725.                                 fprintf(stdout, "X-Chunked: yes\r\n");
  1726.                               }
  1727.                               fprintf(stdout, "\r\n");
  1728.                               /* Send the body */
  1729.                               if (sendb && r.adr) {
  1730.                                 fprintf(stdout, "%s\r\n", r.adr);
  1731.                               }
  1732.                             }
  1733.                           }
  1734.                         }
  1735.                       }
  1736.                     }
  1737.                     freet(cacheNdx);
  1738.                   }
  1739.                 }
  1740.                 if (!found) {
  1741.                   fprintf(stderr, "No cache entry found%s%s%s\r\n",
  1742.                     (hasFilter)?" for '":"",
  1743.                     (hasFilter)?filter:"",
  1744.                     (hasFilter)?"'":""
  1745.                     );
  1746.                 }
  1747.                 htsMemoryFastXfr = backupXFR;
  1748.                 return 0;
  1749.               }
  1750.               break;
  1751.             case 'E':     // extract cache
  1752.               if (!hts_extract_meta(httrack.path_log)) {
  1753.                 fprintf(stderr, "* error extracting meta-data\n");
  1754.                 return 1;
  1755.               }
  1756.               fprintf(stderr, "* successfully extracted meta-data\n");
  1757.               return 0;
  1758.               break;
  1759.             case 'X': 
  1760. #ifndef STRDEBUG
  1761.               fprintf(stderr, "warning: no string debugging support built, option has no effect\n");
  1762. #endif
  1763.               htsMemoryFastXfr=1; 
  1764.               if (*(com+1)=='0') { htsMemoryFastXfr=0; com++; } 
  1765.               break;
  1766.             case 'R':
  1767.               {
  1768.                 char* name;
  1769.                 uLong repaired = 0;
  1770.                 uLong repairedBytes = 0;
  1771.                 if (fexist(fconcat(httrack.path_log,"hts-cache/new.zip"))) {
  1772.                   name = fconcat(httrack.path_log,"hts-cache/new.zip");
  1773.                 } else if (fexist(fconcat(httrack.path_log,"hts-cache/old.zip"))) {
  1774.                   name = fconcat(httrack.path_log,"hts-cache/old.zip");
  1775.                 } else {
  1776.                   fprintf(stderr, "* error: no cache found in %s\n", fconcat(httrack.path_log,"hts-cache/new.zip"));
  1777.                   return 1;
  1778.                 }
  1779.                 fprintf(stderr, "Cache: trying to repair %s\n", name);
  1780.                 if (unzRepair(name, 
  1781.                   fconcat(httrack.path_log,"hts-cache/repair.zip"),
  1782.                   fconcat(httrack.path_log,"hts-cache/repair.tmp"),
  1783.                   &repaired, &repairedBytes
  1784.                   ) == Z_OK) {
  1785.                   unlink(name);
  1786.                   rename(fconcat(httrack.path_log,"hts-cache/repair.zip"), name);
  1787.                   fprintf(stderr,"Cache: %d bytes successfully recovered in %d entries\n", (int) repairedBytes, (int) repaired);
  1788.                 } else {
  1789.                   fprintf(stderr, "Cache: could not repair the cache\n");
  1790.                 }
  1791.               }
  1792.               return 0;
  1793.               break;
  1794.             case '~': /* internal lib test */
  1795.               {
  1796.                 char thisIsATestYouShouldSeeAnError[12];
  1797.                 strcpybuff(thisIsATestYouShouldSeeAnError, "0123456789012345678901234567890123456789");
  1798.                 return 0;
  1799.               }
  1800.               break;
  1801.             case 'f': httrack.flush=1; break;
  1802.             case 'h':
  1803.               printf("HTTrack version "HTTRACK_VERSION"%s\n", WHAT_is_available);
  1804.               return 0;
  1805.               break;
  1806.             case 'p': /* httrack.aff_progress=1; deprecated */ break;
  1807.             case 'S': httrack.shell=1; break;  // stdin sur un shell
  1808.             case 'K': httrack.keyboard=1; break;  // vΘrifier stdin
  1809.               //
  1810.             case 'L': sscanf(com+1,"%d",&httrack.maxlink); while(isdigit((unsigned char)*(com+1))) com++; break;
  1811.             case 'F': sscanf(com+1,"%d",&httrack.maxfilter); while(isdigit((unsigned char)*(com+1))) com++; break;
  1812.             case 'Z': httrack.makestat=1; break;
  1813.             case 'T': httrack.maketrack=1; break;
  1814.             case 'u': sscanf(com+1,"%d",&httrack.waittime); while(isdigit((unsigned char)*(com+1))) com++; break;
  1815.  
  1816.             /*case 'R':    // ohh ftp, catch->ftpget
  1817.               HTS_PANIC_PRINTF("Unexpected internal error with -#R command");
  1818.               htsmain_free();
  1819.               return -1;        
  1820.               break;
  1821.               */
  1822.             case 'P': {     // catchurl
  1823.               help_catchurl(httrack.path_log);
  1824.               htsmain_free();
  1825.               return 0;
  1826.                       }
  1827.               break;
  1828.           
  1829.             case '0':   /* test #0 : filters */
  1830.               if (na+2>=argc) {
  1831.                 HTS_PANIC_PRINTF("Option #0 needs to be followed by a filter string and a string");
  1832.                 printf("Example: '-#0' '*.gif' 'foo.gif'\n");
  1833.                 htsmain_free();
  1834.                 return -1;
  1835.               } else {
  1836.                 if (strjoker(argv[na+2],argv[na+1],NULL,NULL))
  1837.                   printf("%s does match %s\n",argv[na+2],argv[na+1]);
  1838.                 else
  1839.                   printf("%s does NOT match %s\n",argv[na+2],argv[na+1]);
  1840.                 htsmain_free();
  1841.                 return 0;
  1842.               }
  1843.               break;
  1844.             case '1':   /* test #1 : fil_simplifie */
  1845.               if (na+1>=argc) {
  1846.                 HTS_PANIC_PRINTF("Option #1 needs to be followed by an URL");
  1847.                 printf("Example: '-#1' ./foo/bar/../foobar\n");
  1848.                 htsmain_free();
  1849.                 return -1;
  1850.               } else {
  1851.                 fil_simplifie(argv[na+1]);
  1852.                 printf("simplified=%s\n", argv[na+1]);
  1853.                 htsmain_free();
  1854.                 return 0;
  1855.               }
  1856.               break;
  1857.             case '2':   // mimedefs
  1858.               if (na+1>=argc) {
  1859.                 HTS_PANIC_PRINTF("Option #1 needs to be followed by an URL");
  1860.                 printf("Example: '-#2' /foo/bar.php\n");
  1861.                 htsmain_free();
  1862.                 return -1;
  1863.               } else {
  1864.                 char mime[256];
  1865.                 // initialiser mimedefs
  1866.                 get_userhttptype(1,httrack.mimedefs,NULL);
  1867.                 // check
  1868.                 mime[0] = '\0';
  1869.                 get_httptype(mime, argv[na+1], 0);
  1870.                 if (mime[0] != '\0') {
  1871.                   char ext[256];
  1872.                   printf("%s is '%s'\n", argv[na+1], mime);
  1873.                   ext[0] = '\0';
  1874.                   give_mimext(ext, mime);
  1875.                   if (ext[0]) {
  1876.                     printf("and its local type is '.%s'\n", ext);
  1877.                   }
  1878.                 } else {
  1879.                   printf("%s is of an unknown MIME type\n", argv[na+1]);
  1880.                 }
  1881.                 htsmain_free();
  1882.                 return 0;
  1883.               }
  1884.               break;
  1885.             case '!':
  1886.               if (na+1>=argc) {
  1887.                 HTS_PANIC_PRINTF("Option #! needs to be followed by a commandline");
  1888.                 printf("Example: '-#!' 'echo hello'\n");
  1889.                 htsmain_free();
  1890.                 return -1;
  1891.               } else {
  1892.                 system(argv[na+1]);
  1893.               }
  1894.               break;
  1895.             case 'd':
  1896.               httrack.parsedebug = 1;
  1897.               break;
  1898.  
  1899.             /* autotest */
  1900.             case 't':     /* not yet implemented */
  1901.               fprintf(stderr, "** AUTOCHECK OK\n");
  1902.               exit(0);
  1903.               break;
  1904.  
  1905.             default: printf("Internal option %c not recognized\n",*com); break;
  1906.             }
  1907.                      }
  1908.             break; 
  1909.           case 'O':    // output path
  1910.                         while(isdigit(com[1])) {
  1911.                             com++;
  1912.                         }
  1913.             na++;     // sauter, dΘja traitΘ
  1914.             break;
  1915.           case 'P':    // proxy
  1916.             if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1917.               HTS_PANIC_PRINTF("Option P needs to be followed by a blank space, and a proxy proxy:port or user:id@proxy:port");
  1918.               printf("Example: -P proxy.myhost.com:8080\n");
  1919.               htsmain_free();
  1920.               return -1;
  1921.             } else {
  1922.               char* a;
  1923.               na++;
  1924.               httrack.proxy.active=1;
  1925.               // Rechercher MAIS en partant de la fin α cause de user:pass@proxy:port
  1926.               a = argv[na] + strlen(argv[na]) -1;
  1927.               // a=strstr(argv[na],":");  // port
  1928.               while( (a > argv[na]) && (*a != ':') && (*a != '@') ) a--;
  1929.               if (*a == ':') {  // un port est prΘsent, <proxy>:port
  1930.                 sscanf(a+1,"%d",&httrack.proxy.port);
  1931.                 httrack.proxy.name[0]='\0';
  1932.                 strncatbuff(httrack.proxy.name,argv[na],(int) (a - argv[na]));
  1933.               } else {  // <proxy>
  1934.                 httrack.proxy.port=8080;
  1935.                 strcpybuff(httrack.proxy.name,argv[na]);
  1936.               }
  1937.             }
  1938.             break;
  1939.           case 'F':    // user-agent field
  1940.             if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1941.               HTS_PANIC_PRINTF("Option F needs to be followed by a blank space, and a user-agent name");
  1942.               printf("Example: -F \"my_user_agent/1.0\"\n");
  1943.               htsmain_free();
  1944.               return -1;
  1945.             } else{
  1946.               na++;
  1947.               if (strlen(argv[na])>=126) {
  1948.                 HTS_PANIC_PRINTF("User-agent length too long");
  1949.                 htsmain_free();
  1950.                 return -1;
  1951.               }
  1952.               strcpybuff(httrack.user_agent,argv[na]);
  1953.               if (strnotempty(httrack.user_agent))
  1954.                 httrack.user_agent_send=1;
  1955.               else
  1956.                 httrack.user_agent_send=0;    // -F "" dΘsactive l'option
  1957.             }
  1958.             break;
  1959.             //
  1960.           case 'V':    // execute command
  1961.             if ((na+1>=argc) || (argv[na+1][0]=='-')) {
  1962.               HTS_PANIC_PRINTF("Option V needs to be followed by a system-command string");
  1963.               printf("Example: -V \"tar uvf some.tar \\$0\"\n");
  1964.               htsmain_free();
  1965.               return -1;
  1966.             } else{
  1967.               na++;
  1968.               if (strlen(argv[na])>=2048) {
  1969.                 HTS_PANIC_PRINTF("System-command length too long");
  1970.                 htsmain_free();
  1971.                 return -1;
  1972.               }
  1973.               strcpybuff(httrack.sys_com,argv[na]);
  1974.               if (strnotempty(httrack.sys_com))
  1975.                 httrack.sys_com_exec=1;
  1976.               else
  1977.                 httrack.sys_com_exec=0;    // -V "" dΘsactive l'option
  1978.             }
  1979.             break;
  1980.             //
  1981.           default: {
  1982.             char s[HTS_CDLMAXSIZE];
  1983.             sprintf(s,"invalid option %c\n",*com);
  1984.             HTS_PANIC_PRINTF(s);
  1985.             htsmain_free();
  1986.             return -1;
  1987.                    }
  1988.             break;
  1989.           }  // switch
  1990.           com++;    
  1991.         }  // while
  1992.         
  1993.       }  else {  // URL/filters
  1994.         char BIGSTK tempo[1024];       
  1995.         if (strnotempty(url)) strcatbuff(url," ");  // espace de sΘparation
  1996.         strcpybuff(tempo,unescape_http_unharm(argv[na],1));
  1997.         escape_spc_url(tempo);
  1998.         strcatbuff(url,tempo);
  1999.       }  // if argv=- etc. 
  2000.       
  2001.     }  // for
  2002.   }
  2003.   
  2004. #if BDEBUG==3  
  2005.   printf("URLs/filters=%s\n",url);
  2006. #endif
  2007.  
  2008. #if DEBUG_STEPS
  2009.   printf("Analyzing parameters done\n");
  2010. #endif
  2011.  
  2012.  
  2013. #if HTS_WIN
  2014. #else
  2015. #ifndef HTS_DO_NOT_USE_UID
  2016.   /* Chroot - xxc */
  2017.   if (switch_chroot) {
  2018.     uid_t userid=getuid();
  2019.     //struct passwd* userdef=getpwuid(userid);
  2020.     //if (userdef) {
  2021.     if (!userid) {
  2022.       //if (strcmp(userdef->pw_name,"root")==0) {
  2023.       char BIGSTK rpath[1024];
  2024.       //printf("html=%s log=%s\n",httrack.path_html,httrack.path_log);    // xxc
  2025.       if ((httrack.path_html[0]) && (httrack.path_log[0])) {
  2026.         char *a=httrack.path_html,*b=httrack.path_log,*c=NULL,*d=NULL;
  2027.         c=a; d=b;
  2028.         while ((*a) && (*a == *b)) {
  2029.           if (*a=='/') { c=a; d=b; }
  2030.           a++;
  2031.           b++;
  2032.         }
  2033.  
  2034.         rpath[0]='\0';
  2035.         if (c != httrack.path_html) {
  2036.           if (httrack.path_html[0]!='/')
  2037.             strcatbuff(rpath,"./");
  2038.           strncatbuff(rpath,httrack.path_html,(int) (c - httrack.path_html));
  2039.         }
  2040.         {
  2041.           char BIGSTK tmp[1024];
  2042.           strcpybuff(tmp,c); strcpybuff(httrack.path_html,tmp);
  2043.           strcpybuff(tmp,d); strcpybuff(httrack.path_log,tmp);
  2044.         }
  2045.       } else {
  2046.         strcpybuff(rpath,"./");
  2047.         strcpybuff(httrack.path_html,"/");
  2048.         strcpybuff(httrack.path_log,"/");
  2049.       }
  2050.       if (rpath[0]) {
  2051.         printf("[changing root path to %s (path_data=%s,path_log=%s)]\n",rpath,httrack.path_html,httrack.path_log);
  2052.         if (chroot(rpath)) {
  2053.           printf("ERROR! Can not chroot to %s!\n",rpath);
  2054.           return -1;
  2055.         }
  2056.         if (chdir("/")) {     /* new root */
  2057.           printf("ERROR! Can not chdir to %s!\n",rpath);
  2058.           return -1;
  2059.         }
  2060.       } else
  2061.         printf("WARNING: chroot not possible with these paths\n");
  2062.     }
  2063.     //}
  2064.   }
  2065.  
  2066.   /* Setuid */
  2067.   if (switch_uid>=0) {
  2068.     printf("[setting user/group to %d/%d]\n",switch_uid,switch_gid);
  2069.     if (setgid(switch_gid))
  2070.       printf("WARNING! Can not setgid to %d!\n",switch_gid);
  2071.     if (setuid(switch_uid))
  2072.       printf("WARNING! Can not setuid to %d!\n",switch_uid);
  2073.   }
  2074.  
  2075.   /* Final check */
  2076.   {
  2077.     uid_t userid=getuid();
  2078.     if (!userid) {              /* running as r00t */
  2079.       printf("WARNING! You are running this program as root!\n");
  2080.       printf("It might be a good idea to use the -%%U option to change the userid:\n");
  2081.       printf("Example: -%%U smith\n\n");
  2082.     }
  2083.   }
  2084. #endif
  2085. #endif
  2086.   
  2087.   //printf("WARNING! This is *only* a beta-release of HTTrack\n");
  2088.   io_flush;
  2089.   
  2090. #if DEBUG_STEPS
  2091.   printf("Cache & log settings\n");
  2092. #endif
  2093.   
  2094.   // on utilise le cache..
  2095.   // en cas de prΘsence des deux versions, garder la version la plus avancΘe,
  2096.   // cad la version contenant le plus de fichiers  
  2097.   if (httrack.cache) {
  2098.     if (fexist(fconcat(httrack.path_log,"hts-in_progress.lock"))) {   // problemes..
  2099.       if ( fexist(fconcat(httrack.path_log,"hts-cache/new.dat")) ) { 
  2100.         if ( fexist(fconcat(httrack.path_log,"hts-cache/old.zip")) ) {
  2101.           if (fsize(fconcat(httrack.path_log,"hts-cache/new.zip"))<32768) {
  2102.             if (fsize(fconcat(httrack.path_log,"hts-cache/old.zip"))>65536) {
  2103.               if (fsize(fconcat(httrack.path_log,"hts-cache/old.zip")) > fsize(fconcat(httrack.path_log,"hts-cache/new.zip"))) {
  2104.                 remove(fconcat(httrack.path_log,"hts-cache/new.zip"));
  2105.                 rename(fconcat(httrack.path_log,"hts-cache/old.zip"), fconcat(httrack.path_log,"hts-cache/new.zip"));
  2106.               }
  2107.             }
  2108.           }
  2109.         }
  2110.       }
  2111.       else if (fexist(fconcat(httrack.path_log,"hts-cache/new.dat")) && fexist(fconcat(httrack.path_log,"hts-cache/new.ndx"))) { 
  2112.         if (fexist(fconcat(httrack.path_log,"hts-cache/old.dat")) && fexist(fconcat(httrack.path_log,"hts-cache/old.ndx"))) {
  2113.           // switcher si new<32Ko et old>65Ko (tailles arbitraires) ?
  2114.           // ce cas est peut Ωtre une erreur ou un crash d'un miroir ancien, prendre
  2115.           // alors l'ancien cache
  2116.           if (fsize(fconcat(httrack.path_log,"hts-cache/new.dat"))<32768) {
  2117.             if (fsize(fconcat(httrack.path_log,"hts-cache/old.dat"))>65536) {
  2118.               if (fsize(fconcat(httrack.path_log,"hts-cache/old.dat")) > fsize(fconcat(httrack.path_log,"hts-cache/new.dat"))) {
  2119.                 remove(fconcat(httrack.path_log,"hts-cache/new.dat"));
  2120.                 remove(fconcat(httrack.path_log,"hts-cache/new.ndx"));
  2121.                 rename(fconcat(httrack.path_log,"hts-cache/old.dat"),fconcat(httrack.path_log,"hts-cache/new.dat"));
  2122.                 rename(fconcat(httrack.path_log,"hts-cache/old.ndx"),fconcat(httrack.path_log,"hts-cache/new.ndx"));  
  2123.                 //} else {  // ne rien faire
  2124.                 //  remove("hts-cache/old.dat");
  2125.                 //  remove("hts-cache/old.ndx");
  2126.               }
  2127.             }
  2128.           }
  2129.         }
  2130.       }
  2131.     }
  2132.   }
  2133.  
  2134.   // DΘbuggage des en tΩtes
  2135.   if (_DEBUG_HEAD) {
  2136.     ioinfo=fopen(fconcat(httrack.path_log,"hts-ioinfo.txt"),"wb");
  2137.   }
  2138.   
  2139.   {
  2140.     char n_lock[256];
  2141.     // on peut pas avoir un affichage ET un fichier log
  2142.     // ca sera pour la version 2
  2143.     if (httrack_logmode==1) {
  2144.       httrack.log=stdout;
  2145.       httrack.errlog=stderr;
  2146.     } else if (httrack_logmode>=2) {
  2147.       // deux fichiers log
  2148.       structcheck(httrack.path_log);
  2149.       if (fexist(fconcat(httrack.path_log,"hts-log.txt")))
  2150.         remove(fconcat(httrack.path_log,"hts-log.txt"));
  2151.       if (fexist(fconcat(httrack.path_log,"hts-err.txt")))
  2152.         remove(fconcat(httrack.path_log,"hts-err.txt"));
  2153.  
  2154.       /* Check FS directory structure created */
  2155.       structcheck(httrack.path_log);
  2156.  
  2157.       httrack.log=fopen(fconcat(httrack.path_log,"hts-log.txt"),"w");
  2158.       if (httrack_logmode==2)
  2159.         httrack.errlog=fopen(fconcat(httrack.path_log,"hts-err.txt"),"w");
  2160.       else
  2161.         httrack.errlog=httrack.log;
  2162.       if (httrack.log==NULL) {
  2163.         char s[HTS_CDLMAXSIZE];
  2164.         sprintf(s,"Unable to create log file %s",fconcat(httrack.path_log,"hts-log.txt"));
  2165.         HTS_PANIC_PRINTF(s);
  2166.         htsmain_free();
  2167.         return -1;
  2168.       } else if (httrack.errlog==NULL) {
  2169.         char s[HTS_CDLMAXSIZE];
  2170.         sprintf(s,"Unable to create log file %s",fconcat(httrack.path_log,"hts-err.txt"));
  2171.         HTS_PANIC_PRINTF(s);
  2172.         htsmain_free();
  2173.         return -1;
  2174.       }
  2175.  
  2176.     } else {
  2177.       httrack.log=NULL;
  2178.       httrack.errlog=NULL;
  2179.     }
  2180.     
  2181.     // un petit lock-file pour indiquer un miroir en cours, ainsi qu'un Θventuel fichier log
  2182.     {
  2183.       FILE* fp=NULL;
  2184.       //int n=0;
  2185.       char t[256];
  2186.       time_local_rfc822(t);    // faut bien que ca serve quelque part l'heure RFC1945 arf'
  2187.       
  2188.       /* readme for information purpose */
  2189.       {
  2190.         FILE* fp=fopen(fconcat(httrack.path_log,"hts-cache/readme.txt"),"wb");
  2191.         if (fp) {
  2192.           fprintf(fp,"What's in this folder?"LF);
  2193.           fprintf(fp,""LF);
  2194.           fprintf(fp,"This folder (hts-cache) has been generated by WinHTTrack "HTTRACK_VERSION"%s"LF, WHAT_is_available);
  2195.           fprintf(fp,"and is used for updating this website."LF);
  2196.           fprintf(fp,"(The HTML website structure is stored here to allow fast updates)"LF""LF);
  2197.           fprintf(fp,"DO NOT delete this folder unless you do not want to update the mirror in the future!!"LF);
  2198.           fprintf(fp,"(you can safely delete old.zip and old.lst files, however)"LF);
  2199.           fprintf(fp,""LF);
  2200.           fprintf(fp,HTS_LOG_SECURITY_WARNING);
  2201.           fclose(fp);
  2202.         }
  2203.       }
  2204.  
  2205.       sprintf(n_lock,fconcat(httrack.path_log,"hts-in_progress.lock"));
  2206.       //sprintf(n_lock,fconcat(httrack.path_log,"hts-in_progress.lock"),n);
  2207.       /*do {
  2208.         if (!n)
  2209.           sprintf(n_lock,fconcat(httrack.path_log,"hts-in_progress.lock"),n);
  2210.         else
  2211.           sprintf(n_lock,fconcat(httrack.path_log,"hts-in_progress%d.lock"),n);
  2212.         n++;
  2213.       } while((fexist(n_lock)) && httrack.quiet);      
  2214.       if (fexist(n_lock)) {
  2215.         if (!recuperer) {
  2216.           remove(n_lock);
  2217.         }
  2218.       }*/
  2219.  
  2220.       // vΘrifier existence de la structure
  2221.       structcheck(fconcat(httrack.path_html, "/"));
  2222.       structcheck(fconcat(httrack.path_log, "/"));
  2223.      
  2224.       // reprise/update
  2225.       if (httrack.cache) {
  2226.         FILE* fp;
  2227.         int i;
  2228. #if HTS_WIN
  2229.         mkdir(fconcat(httrack.path_log,"hts-cache"));
  2230. #else
  2231.         mkdir(fconcat(httrack.path_log,"hts-cache"),HTS_PROTECT_FOLDER);
  2232. #endif
  2233.         fp=fopen(fconcat(httrack.path_log,"hts-cache/doit.log"),"wb");
  2234.         if (fp) {
  2235.           for(i=0+1;i<argc;i++) {
  2236.             if ( ((strchr(argv[i],' ')!=NULL) || (strchr(argv[i],'"')!=NULL) || (strchr(argv[i],'\\')!=NULL)) && (argv[i][0]!='"')  ) {
  2237.               int j;
  2238.               fprintf(fp,"\"");
  2239.               for(j=0;j<(int) strlen(argv[i]);j++) {
  2240.                 if (argv[i][j]==34)
  2241.                   fprintf(fp,"\\\"");
  2242.                 else if (argv[i][j]=='\\')
  2243.                   fprintf(fp,"\\\\");
  2244.                 else
  2245.                   fprintf(fp,"%c",argv[i][j]);
  2246.               }
  2247.               fprintf(fp,"\"");
  2248.             } else if (strnotempty(argv[i])==0) {   // ""
  2249.               fprintf(fp,"\"\"");
  2250.             } else {   // non critique
  2251.               fprintf(fp,"%s",argv[i]);
  2252.             }
  2253.             if (i<argc-1)
  2254.               fprintf(fp," ");
  2255.           }
  2256.           fprintf(fp,LF);
  2257.           fprintf(fp,"File generated automatically on %s, do NOT edit"LF,t);
  2258.           fprintf(fp,LF);
  2259.           fprintf(fp,"To update a mirror, just launch httrack without any parameters"LF);
  2260.           fprintf(fp,"The existing cache will be used (and modified)"LF);
  2261.           fprintf(fp,"To have other options, retype all parameters and launch HTTrack"LF);
  2262.           fprintf(fp,"To continue an interrupted mirror, just launch httrack without any parameters"LF);
  2263.           fprintf(fp,LF);
  2264.           fclose(fp); fp=NULL;
  2265.         //} else if (httrack.debug>1) {
  2266.         //  printf("! FileOpen error, \"%s\"\n",strerror(errno));
  2267.         }
  2268.       }
  2269.       
  2270.       // petit message dans le lock
  2271.       if ( (fp=fopen(n_lock,"wb"))!=NULL) {
  2272.         int i;
  2273.         fprintf(fp,"Mirror in progress since %s .. please wait!"LF,t);
  2274.         for(i=0;i<argc;i++) {
  2275.           if (strchr(argv[i],' ')==NULL)
  2276.             fprintf(fp,"%s ",argv[i]);
  2277.           else    // entre ""
  2278.             fprintf(fp,"\"%s\" ",argv[i]);
  2279.         }
  2280.         fprintf(fp,LF);
  2281.         fprintf(fp, "To pause the engine: create an empty file named 'hts-stop.lock'"LF);
  2282. #if USE_BEGINTHREAD
  2283.                 fprintf(fp, "PID=%d\n", (int)getpid());
  2284. #ifndef _WIN32
  2285.                 fprintf(fp, "UID=%d\n", (int)getuid());
  2286.                 fprintf(fp, "GID=%d\n", (int)getuid());
  2287. #endif
  2288.                 fprintf(fp, "START=%d\n", (int)time(NULL));
  2289. #endif
  2290.         fclose(fp); fp=NULL;
  2291.       }
  2292.       
  2293.       // fichier log        
  2294.       if (httrack.log)     {
  2295.         int i;
  2296.         fprintf(httrack.log,"HTTrack"HTTRACK_VERSION"%s launched on %s at %s"LF, 
  2297.           WHAT_is_available,
  2298.           t, url);
  2299.         fprintf(httrack.log,"(");
  2300.         for(i=0;i<argc;i++) {
  2301.           if ((strchr(argv[i],' ')==NULL) || (strchr(argv[i],'\"')))
  2302.             fprintf(httrack.log,"%s ",argv[i]);
  2303.           else    // entre "" (si espace(s) et pas dΘja de ")
  2304.             fprintf(httrack.log,"\"%s\" ",argv[i]);
  2305.         }
  2306.         fprintf(httrack.log,")"LF);
  2307.         fprintf(httrack.log,LF);
  2308.         fprintf(httrack.log,"Information, Warnings and Errors reported for this mirror:"LF);
  2309.         fprintf(httrack.log,HTS_LOG_SECURITY_WARNING );
  2310.         fprintf(httrack.log,LF);
  2311.       }
  2312.  
  2313.       if (httrack_logmode) {
  2314.         printf("Mirror launched on %s by HTTrack Website Copier/"HTTRACK_VERSION"%s "HTTRACK_AFF_AUTHORS""LF,t,WHAT_is_available);
  2315.         if (httrack.wizard==0) {
  2316.           printf("mirroring %s with %d levels, %d sockets,t=%d,s=%d,logm=%d,lnk=%d,mdg=%d\n",url,httrack.depth,httrack.maxsoc,httrack.travel,httrack.seeker,httrack_logmode,httrack.urlmode,httrack.getmode);
  2317.         } else {    // the magic wizard
  2318.           printf("mirroring %s with the wizard help..\n",url);
  2319.         }
  2320.       }
  2321.     }
  2322.     
  2323.     io_flush;
  2324.  
  2325.     /* Enforce limits to avoid bandwith abuse. The bypass_limits should only be used by administrators and experts. */
  2326.     if (!httrack.bypass_limits) {
  2327.       if (httrack.maxsoc <= 0 || httrack.maxsoc > 4) {
  2328.         httrack.maxsoc = 4;
  2329.         if (httrack.log != NULL) {
  2330.           fspc(httrack.log,"warning"); fprintf(httrack.log,"* security warning: maximum number of simultaneous connections limited to %d to avoid server overload"LF, (int)httrack.maxsoc);
  2331.         }
  2332.       }
  2333.       if (httrack.maxrate <= 0 || httrack.maxrate > 100000) {
  2334.         httrack.maxrate = 100000;
  2335.         if (httrack.log != NULL) {
  2336.           fspc(httrack.log,"warning"); fprintf(httrack.log,"* security warning: maximum bandwidth limited to %d to avoid server overload"LF, (int)httrack.maxrate);
  2337.         }
  2338.       }
  2339.       if (httrack.maxconn <= 0 || httrack.maxconn > 5.0) {
  2340.         httrack.maxconn = 5.0;
  2341.         if (httrack.log != NULL) {
  2342.           fspc(httrack.log,"warning"); fprintf(httrack.log,"* security warning: maximum number of connections per second limited to %f to avoid server overload"LF, (float)httrack.maxconn);
  2343.         }
  2344.       }
  2345.     } else {
  2346.       if (httrack.log != NULL) {
  2347.         fspc(httrack.log,"warning"); fprintf(httrack.log,"* security warning: !!! BYPASSING SECURITY LIMITS - MONITOR THIS SESSION WITH EXTREME CARE !!!"LF);
  2348.       }
  2349.     }
  2350.  
  2351.   /* Info for wrappers */
  2352.   if ( (httrack.debug>0) && (httrack.log!=NULL) ) {
  2353.     fspc(httrack.log,"info"); fprintf(httrack.log,"engine: init"LF);
  2354.   }
  2355. #if HTS_ANALYSTE
  2356.   if (hts_htmlcheck_init != NULL) {
  2357.     hts_htmlcheck_init();
  2358.   }
  2359.   set_wrappers();   // init() is allowed to set other wrappers
  2360. #endif
  2361.  
  2362.   // dΘtourner SIGHUP etc.
  2363. #if HTS_WIN
  2364. #ifndef  _WIN32_WCE
  2365.   signal( SIGINT  , sig_ask    );   // ^C
  2366.   signal( SIGTERM , sig_finish );   // kill <process>
  2367. #endif
  2368. #else
  2369.   signal( SIGHUP  , sig_back   );   // close window
  2370.   signal( SIGTSTP , sig_back   );   // ^Z
  2371.   signal( SIGTERM , sig_finish );   // kill <process>
  2372.   signal( SIGINT  , sig_ask    );   // ^C
  2373.   signal( SIGPIPE , sig_brpipe );   // broken pipe (write into non-opened socket)
  2374. /*
  2375. deprecated - see SIGCHLD
  2376. #ifndef HTS_DO_NOT_SIGCLD
  2377.   signal( SIGCLD  , sig_ignore );   // child change status
  2378. #endif
  2379. */
  2380.   signal( SIGCHLD , sig_ignore );   // child change status
  2381. #endif
  2382. #if DEBUG_STEPS
  2383.   printf("Launching the mirror\n");
  2384. #endif
  2385.   
  2386.  
  2387.     // Lancement du miroir
  2388.     // ------------------------------------------------------------
  2389.     if (httpmirror(url, &httrack)==0) {
  2390.       printf("Error during operation (see log file), site has not been successfully mirrored\n");
  2391.     } else {
  2392.       if  (httrack.shell) {
  2393.         HTT_REQUEST_START;
  2394.         HT_PRINT("TRANSFER DONE"LF);
  2395.         HTT_REQUEST_END
  2396.       } else {
  2397.         printf("Done.\n");
  2398.       }
  2399.     }
  2400.     // ------------------------------------------------------------
  2401.  
  2402.     //
  2403.     // Build top index
  2404.     if (httrack.dir_topindex) {
  2405.       char BIGSTK rpath[1024*2];
  2406.       char* a;
  2407.       strcpybuff(rpath,httrack.path_html);
  2408.       if (rpath[0]) {
  2409.         if (rpath[strlen(rpath)-1]=='/')
  2410.           rpath[strlen(rpath)-1]='\0';
  2411.       }
  2412.       a=strrchr(rpath,'/');
  2413.       if (a) {
  2414.         *a='\0';
  2415.         hts_buildtopindex(&httrack,rpath,httrack.path_bin);
  2416.         if (httrack.log) {
  2417.           fspc(httrack.log,"info"); fprintf(httrack.log,"Top index rebuilt (done)"LF);
  2418.         }
  2419.       }
  2420.     }
  2421.  
  2422.     if (exit_xh ==1) {
  2423.       if (httrack.log) {
  2424.         fprintf(httrack.log,"* * MIRROR ABORTED! * *\nThe current temporary cache is required for any update operation and only contains data downloaded during the present aborted session.\nThe former cache might contain more complete information; if you do not want to lose that information, you have to restore it and delete the current cache.\nThis can easily be done here by erasing the hts-cache/new.* files]\n");
  2425.       }
  2426.     }
  2427.  
  2428.     /* Info for wrappers */
  2429.     if ( (httrack.debug>0) && (httrack.log!=NULL) ) {
  2430.       fspc(httrack.log,"info"); fprintf(httrack.log,"engine: free"LF);
  2431.     }
  2432. #if HTS_ANALYSTE
  2433.     if (hts_htmlcheck_uninit != NULL) {
  2434.       hts_htmlcheck_uninit();
  2435.     }
  2436. #endif
  2437.  
  2438.     if (httrack_logmode!=1) {
  2439.       if (httrack.errlog == httrack.log) httrack.errlog=NULL;
  2440.       if (httrack.log) { fclose(httrack.log); httrack.log=NULL; }
  2441.       if (httrack.errlog) { fclose(httrack.errlog); httrack.errlog=NULL; }
  2442.     }  
  2443.  
  2444.     // DΘbuggage des en tΩtes
  2445.     if (_DEBUG_HEAD) {
  2446.       if (ioinfo) {
  2447.         fclose(ioinfo);
  2448.       }
  2449.     }
  2450.  
  2451.     // supprimer lock
  2452.     remove(n_lock);
  2453.   }
  2454.  
  2455.   if (x_argvblk)
  2456.     freet(x_argvblk);
  2457.   if (x_argv)
  2458.     freet(x_argv);
  2459.  
  2460. #if HTS_WIN
  2461. #if HTS_ANALYSTE!=2
  2462. //  WSACleanup();    // ** non en cas de thread tjs prΘsent!..
  2463. #endif
  2464. #endif
  2465. #ifdef HTS_TRACE_MALLOC
  2466.   hts_freeall();
  2467. #endif
  2468.  
  2469.   printf("Thanks for using HTTrack!\n");
  2470.   io_flush;
  2471.   htsmain_free();
  2472.   return 0;    // OK
  2473. }
  2474.  
  2475.  
  2476. // main() subroutines
  2477.  
  2478. // vΘrifier chemin path
  2479. int check_path(char* s,char* defaultname) {
  2480.   int i;
  2481.   int return_value=0;
  2482.  
  2483.   // Replace name: ~/mywebsites/# -> /home/foo/mywebsites/#
  2484.   expand_home(s);
  2485.   for(i=0;i<(int) strlen(s);i++)    // conversion \ -> /
  2486.     if (s[i]=='\\')
  2487.       s[i]='/';
  2488.   
  2489.   // remove ending /
  2490.   if (strnotempty(s))
  2491.   if (s[strlen(s)-1]=='/')
  2492.     s[strlen(s)-1]='\0';
  2493.  
  2494.    // Replace name: /home/foo/mywebsites/# -> /home/foo/mywebsites/wonderfulsite
  2495.   if (strnotempty(s)) {
  2496.     if (s[(i=strlen(s))-1]=='#') {
  2497.       if (strnotempty((defaultname?defaultname:""))) {
  2498.         char BIGSTK tempo[HTS_URLMAXSIZE*2];
  2499.         char* a=strchr(defaultname,'#');      // we never know..
  2500.         if (a) *a='\0';
  2501.         tempo[0]='\0';
  2502.         strncatbuff(tempo,s,i-1);
  2503.         strcatbuff(tempo,defaultname);
  2504.         strcpybuff(s,tempo);
  2505.       } else
  2506.         s[0]='\0';            // Clear path (no name/default url given)
  2507.       return_value=1;     // expanded
  2508.     }
  2509.   }
  2510.  
  2511.   // ending /
  2512.   if (strnotempty(s))
  2513.   if (s[strlen(s)-1]!='/')    // ajouter slash α la fin
  2514.     strcatbuff(s,"/");
  2515.  
  2516.   return return_value;
  2517. }
  2518.  
  2519. // dΘtermine si l'argument est une option
  2520. int cmdl_opt(char* s) {
  2521.   if (s[0]=='-') {  // c'est peut Ωtre une option
  2522.     if (strchr(s,'.')!=NULL && strchr(s,'%')==NULL)
  2523.       return 0;    // sans doute un -www.truc.fr (note: -www n'est pas compris)
  2524.     else if (strchr(s,'/')!=NULL)
  2525.       return 0;    // idem, -*cgi-bin/
  2526.     else if (strchr(s,'*')!=NULL)
  2527.       return 0;    // joker, idem
  2528.     else
  2529.       return 1;
  2530.   } else return 0;
  2531. }
  2532.  
  2533.